arcane-os 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +8 -8
  3. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +29 -22
  4. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +203 -0
  5. package/browser-runtime/ai/browser-kokoro-worker.mjs +11 -2
  6. package/browser-runtime/ai/browser-speech-artifacts.mjs +3230 -397
  7. package/browser-runtime/ai/browser-speech-providers.mjs +1141 -157
  8. package/browser-runtime/ai/browser-speech.mjs +2 -0
  9. package/browser-runtime/ai/browser-whisper-worker.mjs +11 -2
  10. package/browser-runtime/ai/model-controller.mjs +285 -95
  11. package/browser-runtime/ai/speech-worker-client.mjs +247 -32
  12. package/browser-runtime/ai/speech-worker-runtime.mjs +2310 -167
  13. package/browser-runtime/event-manager.mjs +1097 -1
  14. package/docs/architecture.md +2 -2
  15. package/docs/event-manager.md +155 -27
  16. package/docs/reference/README.md +20 -20
  17. package/docs/reference/ai/browser-speech-package-authority.json +835 -0
  18. package/docs/reference/ai/browser-speech.md +1162 -246
  19. package/docs/reference/ai/browser-wasm.md +18 -7
  20. package/docs/reference/availability-and-normalization.md +2 -2
  21. package/docs/reference/behavioral-testing.md +28 -5
  22. package/docs/reference/cli.md +115 -7
  23. package/docs/reference/core/arcane-ai-contracts.md +1 -1
  24. package/docs/reference/event-manager.md +577 -32
  25. package/docs/reference/inventory/package-api.json +478 -2
  26. package/docs/reference/inventory/runtime-components.json +86 -37
  27. package/docs/reference/inventory/runtime-modules.json +126 -49
  28. package/docs/reference/mail.md +316 -0
  29. package/docs/reference/protocols.md +143 -33
  30. package/docs/reference/runtime-components.md +192 -80
  31. package/docs/reference/runtime-modules.md +584 -70
  32. package/docs/reference/sdk-api.md +1014 -25
  33. package/package.json +5 -4
  34. package/runtime/ARCANE_RUNTIME_RELEASE.json +145 -140
  35. package/runtime/arcane/components/app-bar.html +34 -13
  36. package/runtime/arcane/components/assistant-panel.html +110 -57
  37. package/runtime/arcane/components/calculator.html +7 -4
  38. package/runtime/arcane/components/chart.html +58 -17
  39. package/runtime/arcane/components/chat.html +606 -136
  40. package/runtime/arcane/components/conversation-view.html +13 -6
  41. package/runtime/arcane/components/dashboard-config.html +96 -59
  42. package/runtime/arcane/components/data-maintenance.html +69 -14
  43. package/runtime/arcane/components/data-view.html +53 -7
  44. package/runtime/arcane/components/directory-picker.html +118 -32
  45. package/runtime/arcane/components/document-inspector.html +47 -10
  46. package/runtime/arcane/components/file-drop.html +81 -35
  47. package/runtime/arcane/components/file-inspector.html +72 -22
  48. package/runtime/arcane/components/file-manager.html +374 -79
  49. package/runtime/arcane/components/integration-settings.html +12 -5
  50. package/runtime/arcane/components/local-ai-status.html +48 -19
  51. package/runtime/arcane/components/markdown-document.html +161 -68
  52. package/runtime/arcane/components/markdown-editor.html +110 -33
  53. package/runtime/arcane/components/media-embed.html +8 -5
  54. package/runtime/arcane/components/modal.html +15 -5
  55. package/runtime/arcane/components/output-panel.html +28 -23
  56. package/runtime/arcane/components/preferences-form.html +22 -4
  57. package/runtime/arcane/components/record-timeline.html +18 -2
  58. package/runtime/arcane/components/relationship-board.html +23 -3
  59. package/runtime/arcane/components/screen-capture.html +10 -4
  60. package/runtime/arcane/components/source-code-viewer.html +76 -9
  61. package/runtime/arcane/components/source-explanation.html +23 -3
  62. package/runtime/arcane/components/speech.html +453 -131
  63. package/runtime/arcane/components/summary-strip.html +22 -11
  64. package/runtime/arcane/components/table.html +39 -21
  65. package/runtime/arcane/components/task-progress.html +79 -21
  66. package/runtime/arcane/components/terminal-workspace.html +7 -4
  67. package/runtime/arcane/components/theme-editor.html +7 -3
  68. package/runtime/arcane/components/unified-inbox.html +9 -4
  69. package/runtime/arcane/components/voice-transcription.html +244 -72
  70. package/runtime/arcane/components/weather-widget.html +5 -3
  71. package/runtime/arcane/components/web-navigator.html +48 -8
  72. package/runtime/arcane/entities/Chat.js +1 -1
  73. package/runtime/arcane/entities/User.js +110 -23
  74. package/runtime/arcane/modules/AI.js +2109 -130
  75. package/runtime/arcane/modules/AIProviderRuntime.js +720 -13
  76. package/runtime/arcane/modules/AIRuntimeState.js +109 -52
  77. package/runtime/arcane/modules/ApiModelDatabase.js +390 -17
  78. package/runtime/arcane/modules/BrowserTestSuite.js +205 -28
  79. package/runtime/arcane/modules/CalculatorEngine.js +63 -3
  80. package/runtime/arcane/modules/CommunicationAppController.js +588 -28
  81. package/runtime/arcane/modules/CommunicationHub.js +590 -10
  82. package/runtime/arcane/modules/ComponentContracts.js +235 -37
  83. package/runtime/arcane/modules/ConversationTimebox.js +152 -33
  84. package/runtime/arcane/modules/DBLS.js +40 -7
  85. package/runtime/arcane/modules/DBOPFS.js +35 -11
  86. package/runtime/arcane/modules/DataMaintenance.js +12 -2
  87. package/runtime/arcane/modules/Errors.js +65 -7
  88. package/runtime/arcane/modules/HTMLImport.js +198 -14
  89. package/runtime/arcane/modules/LocalAIReadinessController.js +208 -29
  90. package/runtime/arcane/modules/Mail.js +738 -115
  91. package/runtime/arcane/modules/MailOutbox.mjs +1395 -0
  92. package/runtime/arcane/modules/MailTransport.mjs +197 -39
  93. package/runtime/arcane/modules/Ollama.js +36 -1
  94. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +583 -7
  95. package/runtime/arcane/modules/PreferenceStore.js +367 -33
  96. package/runtime/arcane/modules/RecordReviewStore.js +322 -23
  97. package/runtime/arcane/modules/ScreenCapture.js +1397 -15
  98. package/runtime/arcane/modules/SpeechPlayback.js +438 -41
  99. package/runtime/arcane/modules/TerminalClient.js +277 -12
  100. package/runtime/arcane/modules/ThemeBootstrap.js +80 -6
  101. package/runtime/arcane/modules/ThemeManager.js +39 -7
  102. package/runtime/arcane/modules/TimeGuard.js +131 -20
  103. package/runtime/arcane/modules/WaitForComponent.js +386 -33
  104. package/schemas/arcane-lock.schema.json +2 -2
  105. package/src/cli/main.mjs +435 -9
  106. package/src/event-manager.mjs +1097 -1
  107. package/src/import-map.mjs +21 -3
  108. package/src/index.mjs +13 -0
  109. package/src/installed-sdk-runtime.mjs +112 -0
  110. package/src/mail-api.mjs +22 -0
  111. package/src/mail-credentials.mjs +667 -0
  112. package/src/mail-server.mjs +1769 -0
  113. package/src/mail.mjs +261 -0
  114. package/src/sdk-browser-runtime.mjs +85 -41
  115. package/src/testing-loader.mjs +7 -0
  116. package/src/toolchain.mjs +3 -0
  117. package/src/workspace.mjs +1 -1
@@ -1,20 +1,24 @@
1
1
  # EventManager and time-travel diagnostics
2
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.
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.
7
8
 
8
9
  The API is capability-first:
9
10
 
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;
11
15
  - recording creates immutable, normalized `arcane-event-stack/1` records;
12
16
  - browser DOM capture is opt-in and privacy-preserving by default;
13
17
  - review playback is safe by default; live event redispatch is explicitly effectful;
14
18
  - no event stack is uploaded, persisted, bridged to Core, or sent to a cloud service
15
19
  automatically.
16
20
 
17
- All 20 JavaScript exports are available from both `arcane-os` and
21
+ All 32 JavaScript exports are available from both `arcane-os` and
18
22
  `arcane-os/event-manager`. The bindings are identical, so choose the focused
19
23
  subpath when event instrumentation is the only SDK capability you need. Node
20
24
  can resolve either package entrypoint. The generated browser map intentionally
@@ -26,36 +30,43 @@ root.
26
30
  ```javascript
27
31
  import {
28
32
  arcaneEvents,
33
+ createArcaneEventSource,
34
+ createEventManager,
35
+ projectArcaneDOMEvent,
29
36
  PLAYBACK_RECORD_EVENT
30
37
  } from 'arcane-os/event-manager';
31
38
 
32
- arcaneEvents.on('document.save.completed',event=>{
33
- console.info('Saved',event.documentId);
39
+ const events=createArcaneEventSource(editorController,{
40
+ source:'app.editor',
41
+ eventTypes:['document.save.completed']
34
42
  });
35
43
 
36
- arcaneEvents.enableTimeTravel();
37
- try{
38
- arcaneEvents.instrument(
39
- 'document.save.completed',
40
- {documentId:'example'},
41
- {source:'app:editor',category:'operation',correlationId:'save-42'}
42
- );
43
- }finally{
44
- arcaneEvents.disableTimeTravel();
45
- }
44
+ const unsubscribe=arcaneEvents.subscribe('document.save.completed',occurrence=>{
45
+ console.info('Saved',occurrence.detail.documentId);
46
+ });
46
47
 
47
- const stack=arcaneEvents.exportStack();
48
- arcaneEvents.on(PLAYBACK_RECORD_EVENT,record=>console.info(record.type));
49
- await arcaneEvents.playback({stack,mode:'review',speed:0});
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});
50
60
  ```
51
61
 
52
- Recording is disabled on `arcaneEvents` by default. Keep diagnostic sessions
53
- bounded, export intentionally, then call `clearHistory()`.
62
+ Recording is disabled by default. Keep isolated diagnostic sessions bounded,
63
+ export intentionally, then call `clearHistory()`.
54
64
 
55
65
  ## Availability and normalization
56
66
 
57
67
  | Capability | Node | Browser renderer | Native/Core host | Remote or cloud | Normalization |
58
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` |
59
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 |
60
71
  | DOM selectors and target descriptions | With DOM-like values or a test shim | Yes | No native UI observation | No | Stable diagnostic descriptors |
61
72
  | DOM interaction and mutation capture | No native DOM | Yes | No | No | DOM activity becomes semantic event-stack records |
@@ -77,6 +88,15 @@ service.
77
88
  | Export | Kind | Primary capability |
78
89
  | --- | --- | --- |
79
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 |
80
100
  | `TIME_TRAVEL_SEEK_EVENT` | String constant | Observe review-cursor movement |
81
101
  | `PLAYBACK_STARTED_EVENT` | String constant | Observe playback startup |
82
102
  | `PLAYBACK_RECORD_EVENT` | String constant | Receive safe review records |
@@ -95,7 +115,10 @@ service.
95
115
  | `parseEventStack()` | Function | Strictly import and freeze a stack |
96
116
  | `EventManager` | Class | Create an isolated bus and timeline |
97
117
  | `createEventManager()` | Function | Create an `EventManager` |
98
- | `arcaneEvents` | `EventManager` singleton | Observe shared SDK events |
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 |
99
122
 
100
123
  ## `EventManager`
101
124
 
@@ -314,26 +337,522 @@ const events=createEventManager({timeTravel:true,maxEvents:1_000});
314
337
 
315
338
  ### Overview
316
339
 
317
- The SDK-wide `EventManager` singleton. Recording is off by default. SDK operation
318
- queues forward each normalized event object through this manager before their
319
- awaited callback; nested queues deduplicate the same object identity.
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.
320
347
 
321
348
  ### Value
322
349
 
323
350
  ```javascript
324
- const arcaneEvents = new EventManager()
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);
325
751
  ```
326
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
+
327
846
  ### Availability and normalization
328
847
 
329
- One singleton per resolved SDK module graph in Node or a browser bundle. It is not
330
- a cross-process, cross-frame, Core, native, or cloud singleton.
848
+ **Node and browser/bundler.** One handle belongs to one active owner in one
849
+ realm and declares every publishable type before use.
331
850
 
332
851
  ### Example
333
852
 
334
853
  ```javascript
335
- import {arcaneEvents} from 'arcane-os';
336
- arcaneEvents.on('sdk.operation.completed',event=>console.info(event));
854
+ import {ARCANE_EVENT_SOURCE_PROTOCOL} from 'arcane-os/event-manager';
855
+ console.log(source.protocol===ARCANE_EVENT_SOURCE_PROTOCOL);
337
856
  ```
338
857
 
339
858
  ## `parseEventStack()`
@@ -923,6 +1442,29 @@ kernel/application snapshot.
923
1442
 
924
1443
  | Operation | Error | Recovery |
925
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 |
926
1468
  | Constructor flags, clocks, or session id invalid | `TypeError` | Correct types; keep session id non-empty and at most 256 characters |
927
1469
  | Constructor/import retention or snapshot limits invalid | `RangeError` | Use positive safe integers and keep `maxSnapshotStringLength` at least 64 |
928
1470
  | Clock returns invalid timestamp or monotonic value | `TypeError` | Supply a valid UTC-compatible clock and finite non-negative monotonic clock |
@@ -948,7 +1490,10 @@ The executable contract is covered by:
948
1490
  stack-suppression defaults, minimum-budget BigInt/collision/truncation round
949
1491
  trips, strict forged-import rejection, cursor behavior, review and event
950
1492
  playback, cancellation, bounded overflow, attach-at-limit cleanup, recovery,
951
- and central queue mirroring;
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;
952
1497
  - `test/dom-event-instrumentation.test.mjs`: browser interaction/mutation capture,
953
1498
  open-shadow observation, privacy defaults, lifecycle, and cleanup;
954
1499
  - `test/contracts.test.mjs`: published schema and package-export stability;