arcane-os 0.5.9 → 0.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +117 -26
- package/browser-runtime/ai/browser-speech-providers.mjs +1 -1
- package/browser-runtime/ai/browser-wasm-llm-provider.mjs +63 -39
- package/docs/architecture.md +303 -0
- package/docs/compatibility.md +38 -0
- package/docs/event-manager.md +263 -0
- package/docs/platform-targets.md +104 -0
- package/docs/publishing.md +126 -0
- package/docs/reference/README.md +206 -0
- package/docs/reference/ai/browser-speech.md +813 -0
- package/docs/reference/ai/browser-wasm.md +637 -0
- package/docs/reference/ai/twin-cloud.md +156 -0
- package/docs/reference/arcane-ollama.md +288 -0
- package/docs/reference/availability-and-normalization.md +224 -0
- package/docs/reference/behavioral-testing.md +129 -0
- package/docs/reference/cli.md +820 -0
- package/docs/reference/core/README.md +61 -0
- package/docs/reference/core/arcane-ai-contracts.md +907 -0
- package/docs/reference/core/arcane-api.md +601 -0
- package/docs/reference/core/arcane-entities.md +59 -0
- package/docs/reference/core/arcane-events.md +134 -0
- package/docs/reference/core/ollama-module.md +181 -0
- package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
- package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
- package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
- package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
- package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
- package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
- package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
- package/docs/reference/event-manager.md +1409 -0
- package/docs/reference/inventory/package-api.json +3194 -0
- package/docs/reference/inventory/runtime-components.json +1015 -0
- package/docs/reference/inventory/runtime-entities.json +25 -0
- package/docs/reference/inventory/runtime-modules.json +1367 -0
- package/docs/reference/mail.md +309 -0
- package/docs/reference/protocols.md +749 -0
- package/docs/reference/runtime-components.md +1529 -0
- package/docs/reference/runtime-entities.md +305 -0
- package/docs/reference/runtime-modules.md +3275 -0
- package/docs/reference/sdk-api.md +6733 -0
- package/docs/roadmap.md +79 -0
- package/docs/work-amplification.md +66 -0
- package/examples/wasm-ai-demo/README.md +80 -0
- package/examples/wasm-ai-demo/app.js +787 -0
- package/examples/wasm-ai-demo/index.html +343 -0
- package/examples/wasm-ai-demo/profile-tools.js +217 -0
- package/examples/wasm-ai-demo/profiles/BOSS.Modelfile +106 -0
- package/examples/wasm-ai-demo/profiles/PreCrisis.Modelfile +693 -0
- package/examples/wasm-ai-demo/rag/boss-library.json +3006 -0
- package/examples/wasm-ai-demo/rag.js +295 -0
- package/examples/wasm-ai-demo/server.mjs +71 -0
- package/package.json +11 -2
- package/runtime/arcane/modules/AI.js +1 -1
- package/runtime/arcane/modules/AIProviderRuntime.js +26 -5
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
The CLI, future Arcane Developer graphical control panel, CI, and Codex all use
|
|
4
|
+
one headless operation API. A client selects a named operation and consumes the
|
|
5
|
+
same structured event stream; the GUI is not a second build system.
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
external app repository -----+
|
|
9
|
+
|
|
|
10
|
+
Arcane OS consumer checkout --+-- CLI / future GUI / Codex / CI
|
|
11
|
+
|
|
|
12
|
+
shared toolchain API
|
|
13
|
+
|
|
|
14
|
+
browser package or explicit target adapter
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Canonical ownership and portability boundary
|
|
18
|
+
|
|
19
|
+
The SDK repository is the canonical source for every mechanism that can be
|
|
20
|
+
reused by a portable Arcane application. That includes shared modules,
|
|
21
|
+
entities, components, themes, browser runtimes, providers, workers and assets;
|
|
22
|
+
protocol, state, startup, readiness, progress, cancellation, unload and dispose
|
|
23
|
+
machinery; public native contracts and adapters; the development source mount;
|
|
24
|
+
and the packaging and license boundaries for that portable content. In
|
|
25
|
+
particular, shared AI selected-role hydration, startup-settled state and events,
|
|
26
|
+
role readiness, lifecycle and
|
|
27
|
+
cancellation contracts, and the shared chat and speech components are
|
|
28
|
+
SDK-owned source and contracts rather than Arcane OS–owned snapshots.
|
|
29
|
+
|
|
30
|
+
Every portable application artifact materializes the complete SDK runtime,
|
|
31
|
+
assets, workers, licenses and public contracts it uses. It remains self-contained whether it runs as plain
|
|
32
|
+
HTML or inside an executable wrapper. It has no runtime dependency on an
|
|
33
|
+
Arcane OS installation, source checkout or private Arcane OS import.
|
|
34
|
+
|
|
35
|
+
Arcane OS is an SDK consumer like other applications. Its orchestrator,
|
|
36
|
+
launcher, Shell, Provisioner, system AI application and internal tools use the
|
|
37
|
+
same SDK modules and components rather than maintaining private runtime copies.
|
|
38
|
+
Arcane OS and Core own the privileged host implementations, app/session
|
|
39
|
+
admission and authorization, native transport and lifecycle, launcher and
|
|
40
|
+
Shell orchestration, and system-AI policy specific to the Shell. The SDK may
|
|
41
|
+
publish the capability-neutral Core bridge contract and adapters, but it does
|
|
42
|
+
not embed Core or inherit another application's policy.
|
|
43
|
+
|
|
44
|
+
Each application owns its branding, prompts, data, tools, business policy,
|
|
45
|
+
model authorities and app-specific orchestration. Apply this decision order:
|
|
46
|
+
|
|
47
|
+
| Responsibility | Canonical owner |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Reusable by any portable application | Arcane SDK |
|
|
50
|
+
| Host privilege, launcher, Shell or app/session admission | Arcane OS / Core |
|
|
51
|
+
| Behavior unique to one product | That application |
|
|
52
|
+
|
|
53
|
+
Do not copy a reusable implementation between the SDK, Arcane OS and an app,
|
|
54
|
+
and do not create a hidden Arcane OS source dependency. Extend one neutral SDK
|
|
55
|
+
contract and keep product policy in the consumer.
|
|
56
|
+
|
|
57
|
+
Application and consumer tasks do not modify this repository's SDK source and
|
|
58
|
+
do not hand-edit materialized `arcane/**` projections. They request a reusable
|
|
59
|
+
change from an SDK source owner, or implement behavior that is specific to their
|
|
60
|
+
product in that application's local source. Consumer projections change only
|
|
61
|
+
through the selected public package and materializer.
|
|
62
|
+
|
|
63
|
+
Development and distribution use different authority. The explicit
|
|
64
|
+
`arcane dev --sdk-runtime-source <sdk-root>` development-only live source mount
|
|
65
|
+
lets a refresh read the saved SDK source without copying it into the app.
|
|
66
|
+
Distribution never follows that mount. It embeds the application's complete
|
|
67
|
+
selected SDK projection.
|
|
68
|
+
|
|
69
|
+
`runtime/arcane/` is the SDK-canonical source. Arcane OS must consume the
|
|
70
|
+
selected SDK projection through the same package/source-mount boundary as
|
|
71
|
+
other apps; its repository-side consumer cutover is coordinated separately and
|
|
72
|
+
does not create a co-equal source. Git history records the completed ownership
|
|
73
|
+
migration; the current tree has no OS-to-SDK synchronization path.
|
|
74
|
+
|
|
75
|
+
## Workspace profiles
|
|
76
|
+
|
|
77
|
+
An external workspace maps the exact runtime shipped by its locked `arcane-os`
|
|
78
|
+
dependency. An Arcane OS checkout is an integrated SDK consumer, not the owner
|
|
79
|
+
of portable runtime source. For live shared development, the explicit
|
|
80
|
+
development-only SDK source mount maps the canonical SDK runtime and dependency
|
|
81
|
+
paths into that consumer. Without the mount, the workspace uses its locked SDK
|
|
82
|
+
projection. The development server and packager consume the same route
|
|
83
|
+
destinations in both cases, so app imports do not change. Integrated
|
|
84
|
+
initialization creates only app-owned files and never rewrites Arcane OS or SDK
|
|
85
|
+
root configuration.
|
|
86
|
+
|
|
87
|
+
The shared/Core development profile is a separate integrated-only scope selected
|
|
88
|
+
with `--scope shared`. The SDK loads exactly
|
|
89
|
+
`tools/integrated-development-provider.mjs` from the selected Arcane OS checkout
|
|
90
|
+
as one process generation. This is a privileged host-development provider, not
|
|
91
|
+
a source of portable SDK runtime content. That provider selects only one exact
|
|
92
|
+
repository-relative focused `.test.mjs` through Arcane's canonical focused
|
|
93
|
+
runner or Arcane's canonical development check. External workspaces cannot use
|
|
94
|
+
the scope, and shared operations never enter app discovery, packaging, target
|
|
95
|
+
planning, build, verification, or run paths. A generation change requires a new
|
|
96
|
+
CLI process.
|
|
97
|
+
Integrated app testing remains isolated to the selected `apps/<id>/test/`
|
|
98
|
+
tree; it cannot recursively select Arcane root tests or another app's tests.
|
|
99
|
+
External repositories retain their existing workspace-root plus selected-app
|
|
100
|
+
test layout.
|
|
101
|
+
|
|
102
|
+
## Development and release serving boundary
|
|
103
|
+
|
|
104
|
+
Arcane applications keep one browser-first plain HTML, CSS, and JavaScript
|
|
105
|
+
baseline. A native target runs that same application and progressively enhances
|
|
106
|
+
it through capability-gated Arcane Core access. Browser operation must not
|
|
107
|
+
depend on Core being present. A feature that genuinely requires Core reports
|
|
108
|
+
its unavailability without breaking unrelated browser
|
|
109
|
+
behavior or claiming that the capability exists.
|
|
110
|
+
|
|
111
|
+
Rapid development uses `arcane dev`. The development server maps the selected
|
|
112
|
+
application's canonical source tree and the live installed SDK/runtime routes.
|
|
113
|
+
Each request reads and returns the complete current saved source, so a browser
|
|
114
|
+
refresh shows source changes without packaging, copying
|
|
115
|
+
files into `dist`, or restarting the server. Restarting is not a content
|
|
116
|
+
synchronization step; when a refresh is stale, first verify the command, URL,
|
|
117
|
+
workspace, selected app, and resolved source route.
|
|
118
|
+
|
|
119
|
+
Development is an intentionally fast feedback loop. Keep each increment small
|
|
120
|
+
and independently understandable so its effect has one clear cause and a
|
|
121
|
+
mistake can be isolated without untangling unrelated work. A development
|
|
122
|
+
operation does not implicitly run tests, checks, packaging, builds, or release
|
|
123
|
+
verification. The developer invokes a focused test or check deliberately at an
|
|
124
|
+
explicit checkpoint; merely refreshing source does not trigger one.
|
|
125
|
+
|
|
126
|
+
Executable development uses an Arcane-owned native development wrapper around
|
|
127
|
+
the same source-serving browser surface. The wrapper is an escalated browser,
|
|
128
|
+
not a packaged application: it loads current source files and adds only the
|
|
129
|
+
selected application's declared, capability-gated local Arcane Core access.
|
|
130
|
+
It preserves the browser behavior when Core is absent, reports an unavailable
|
|
131
|
+
native-only capability honestly, and never silently substitutes a release
|
|
132
|
+
tree. Starting or refreshing this wrapper does not package, copy to `dist`, or
|
|
133
|
+
run tests automatically. The SDK must not describe native source development as
|
|
134
|
+
available until this wrapper and its explicit capability boundary are actually
|
|
135
|
+
implemented.
|
|
136
|
+
|
|
137
|
+
Packaging and release verification are separate explicit operations. Run
|
|
138
|
+
`arcane package` to generate `dist/<id>`, then use
|
|
139
|
+
`arcane run --target browser` to serve that selected release. Packaging does
|
|
140
|
+
not automatically run tests or checks; those run only when the user expressly
|
|
141
|
+
requests them or when required for a separately selected release output. The browser
|
|
142
|
+
run command does not substitute source files. If source changes after
|
|
143
|
+
packaging, the prior `dist` remains intentionally unchanged until the next
|
|
144
|
+
explicit package operation. Never use packaged `dist` as the everyday
|
|
145
|
+
development tree, and never treat source-serving behavior as evidence for the
|
|
146
|
+
release artifact.
|
|
147
|
+
|
|
148
|
+
## App and release contract
|
|
149
|
+
|
|
150
|
+
The first SDK version deliberately preserves Arcane's current repository-shaped
|
|
151
|
+
URLs and release schema:
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
apps/<id>/arcane-app.json
|
|
155
|
+
apps/<id>/arcane-package.json
|
|
156
|
+
apps/<id>/index.html
|
|
157
|
+
dist/<id>/ARCANE_APP_RELEASE.json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The authored schema-2 descriptor is canonical for new apps and projects an
|
|
161
|
+
exact schema-1 `arcane-package.json` for current consumers. Existing Arcane
|
|
162
|
+
apps synthesize that descriptor from their schema-1 package plus the current
|
|
163
|
+
native registry during migration.
|
|
164
|
+
|
|
165
|
+
An external app's `arcane-packager.json` has three exact shared routes. They map
|
|
166
|
+
the installed SDK runtime to `/arcane`, its vendored strong-type dependency to
|
|
167
|
+
`/node_modules/strong-type`, and the SDK's `LICENSE`,
|
|
168
|
+
`COMMERCIAL-LICENSE.md`, and `NOTICE` to `/licenses/arcane-os`. Development does
|
|
169
|
+
not copy SDK runtime source into the app repository. Distribution materializes
|
|
170
|
+
those selected SDK routes completely inside the portable artifact, so the
|
|
171
|
+
finished app has no Arcane OS runtime dependency.
|
|
172
|
+
|
|
173
|
+
Release schema 1 and builder identity `arcane-app-packager-v1` remain unchanged
|
|
174
|
+
because current Arcane native consumers treat them as public contracts. Native
|
|
175
|
+
builders consume the schema-2 descriptor as a separate build input while v1
|
|
176
|
+
host artifacts remain unchanged.
|
|
177
|
+
|
|
178
|
+
External repository delivery adds a distinct schema-1
|
|
179
|
+
`arcane-app-release-bundle` envelope. Bundle creation uses an authored schema-2
|
|
180
|
+
`arcane-app.json`; a synthesized package or registry projection remains valid for integrated
|
|
181
|
+
packaging but is not used for an external bundle. The
|
|
182
|
+
archive contains exactly `ARCANE_APP_BUNDLE.json`, canonical `arcane-app.json`,
|
|
183
|
+
`payload/ARCANE_APP_RELEASE.json`, and the release inventory beneath `payload/`
|
|
184
|
+
in that order. The envelope adds no repository-only source or build tooling
|
|
185
|
+
beyond that selected release inventory. Individual apps remain responsible for
|
|
186
|
+
their authored source policy.
|
|
187
|
+
|
|
188
|
+
The bundle contract uses the documented USTAR+gzip structure. Explicit bundle
|
|
189
|
+
verification parses the selected archive without extraction and rejects
|
|
190
|
+
genuinely malformed structures, unsafe or colliding paths, unsupported members,
|
|
191
|
+
trailing data, and incompatible bundle generations. These corrupt-artifact
|
|
192
|
+
checks do not create byte-count, content-hash, provenance, or admission gates
|
|
193
|
+
for ordinary development, packaging, serving, or running.
|
|
194
|
+
|
|
195
|
+
Promotion preserves any prior output until the new archive is complete.
|
|
196
|
+
Pre-commit failure restores that backup when doing so will not overwrite a
|
|
197
|
+
concurrent change; otherwise the uncertain paths remain available for
|
|
198
|
+
inspection. Ordinary results report the selected artifact and complete
|
|
199
|
+
inventory without byte identities. The workflow creates no provenance,
|
|
200
|
+
attestation, signing, or restrictive admission record.
|
|
201
|
+
|
|
202
|
+
The governing reusable app-release contract uses one `contents: read` job to
|
|
203
|
+
check out the selected caller revision, perform the caller's normal locked
|
|
204
|
+
install, package and bundle one selected app, and upload that complete bundle.
|
|
205
|
+
The checked-in workflow is unavailable until it matches this contract. The
|
|
206
|
+
contract does not include a second verifier or privileged attestation job.
|
|
207
|
+
|
|
208
|
+
## Operation ownership
|
|
209
|
+
|
|
210
|
+
An invocation defaults to one workspace, one app, one command, one target, one
|
|
211
|
+
architecture, one format, and one signing profile. It acknowledges before long
|
|
212
|
+
work, uses one `AbortController`, supervises child processes, and routes progress
|
|
213
|
+
through one serialized owned event queue. Process streams apply pause/resume
|
|
214
|
+
backpressure and heartbeats coalesce. Callback failure cancels owned work, drains
|
|
215
|
+
the queue, and reaches the caller or CLI exit status. Packaging preserves prior
|
|
216
|
+
output until replacement is complete.
|
|
217
|
+
|
|
218
|
+
Each normalized queue event is also mirrored exactly once through the shared
|
|
219
|
+
`arcaneEvents` `EventManager`. That synchronous `event-pubsub` route is the
|
|
220
|
+
canonical cross-cutting instrumentation surface, but it does not replace the
|
|
221
|
+
owned asynchronous callback path or its backpressure. Time-travel history and
|
|
222
|
+
DOM observation remain explicitly disabled unless a diagnostic session enables
|
|
223
|
+
them. See [event-manager.md](event-manager.md) for the complete record, capture,
|
|
224
|
+
DOM coverage, and effect-isolated playback boundaries.
|
|
225
|
+
|
|
226
|
+
For `--scope shared`, the cardinality changes to one integrated workspace, one
|
|
227
|
+
named operation, and either one exact test file or one development check. The
|
|
228
|
+
same owned event queue and process supervisor provide acknowledgement, complete
|
|
229
|
+
stream delivery with backpressure, heartbeat, cancellation, process-tree
|
|
230
|
+
cleanup, and nonzero
|
|
231
|
+
failure propagation. No app or target loop exists in that scope.
|
|
232
|
+
|
|
233
|
+
## Complete-content ordinary path
|
|
234
|
+
|
|
235
|
+
Packaging writes the complete schema-1 release inventory to
|
|
236
|
+
`ARCANE_APP_RELEASE.json`. Ordinary development, packaging, serving, and run
|
|
237
|
+
paths do not count, limit, hash, truncate, tail, clip, or identify content by
|
|
238
|
+
bytes, and they do not require provenance or verification receipts. The
|
|
239
|
+
loopback server reads and returns each complete selected source, runtime, or
|
|
240
|
+
packaged file. Required credential protection, malformed-input rejection,
|
|
241
|
+
applicable law, unavoidable protocol rules, and operating-system or browser
|
|
242
|
+
safety remain in effect.
|
|
243
|
+
|
|
244
|
+
## Native provider boundary
|
|
245
|
+
|
|
246
|
+
The SDK implements protocol `arcane-native-build-plan/1` and the injected
|
|
247
|
+
provider contract `arcane-native-builder/1`. Pairing is process-local; it never
|
|
248
|
+
registers a mutable global provider or searches for a toolchain. For each
|
|
249
|
+
supported native target, the CLI loads one fixed provider module from the
|
|
250
|
+
explicit `--arcane-root` Arcane OS checkout. Provider code is bound to one
|
|
251
|
+
process generation; if a pull changes loaded provider code, the caller starts a
|
|
252
|
+
fresh worker. One paired toolchain can perform this lifecycle:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
doctor -> prepare -> plan -> build -> run
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
The portable provider reports honestly that run is unavailable because its
|
|
259
|
+
result is a directory. Windows x64, Linux x64,
|
|
260
|
+
Linux ARM64, and Android ARM64 implement same-process launch and owned
|
|
261
|
+
cancellation when their compatible host/device requirements are present.
|
|
262
|
+
Windows uses a retained per-build broker and host readiness. The
|
|
263
|
+
Linux provider produces an amd64 or ARM64 DEB and runs a retained
|
|
264
|
+
user-owned extraction without install or elevation. Portable, Windows, and
|
|
265
|
+
Linux use the `unsigned-local-test` signing profile.
|
|
266
|
+
|
|
267
|
+
The Android provider produces one development-signed APK. It contains no native
|
|
268
|
+
library or ABI-specific payload, so the artifact is architecture-neutral; the
|
|
269
|
+
`android-arm64` target instead binds the supported run path to one physical
|
|
270
|
+
device with native ARM64 support. APK is the only Android format in this
|
|
271
|
+
development provider. AAB, release signing, publishing, and update continuity
|
|
272
|
+
remain outside it.
|
|
273
|
+
|
|
274
|
+
The plan selects one explicit `toolchainRoot`, one app release root, its
|
|
275
|
+
schema-2 descriptor, only its
|
|
276
|
+
declared dependency releases, one non-overlapping output root, and one target,
|
|
277
|
+
platform, architecture, format, and signing request. App source and workspace
|
|
278
|
+
paths are withheld from the native provider. The provider copies the complete
|
|
279
|
+
selected release rather than accepting an unrelated source path. Verification
|
|
280
|
+
is a separate explicit operation for a selected release artifact.
|
|
281
|
+
|
|
282
|
+
The SDK `0.5.11` runtime requires Arcane `0.8.12` or newer. Compatibility
|
|
283
|
+
is contractual rather than exact-version pinning: the prepared Core must meet
|
|
284
|
+
the highest minimum declared by the runtime, selected app, and bundled app
|
|
285
|
+
dependencies; keep each app's Arcane protocol generation; and provide every
|
|
286
|
+
declared feature, capability, and method. Missing requirements stop before
|
|
287
|
+
provider build; a newer compatible Core is accepted. Browser-only apps may omit
|
|
288
|
+
`minimumCoreVersion`, and missing permissions or optional security declarations
|
|
289
|
+
normalize to empty records. The provider paths have
|
|
290
|
+
been validated from independent workspaces. They do not copy proprietary source
|
|
291
|
+
into the Arcane checkout.
|
|
292
|
+
|
|
293
|
+
See [compatibility.md](compatibility.md) for the complete app and bundled-app
|
|
294
|
+
compatibility rule and the required handling of breaking contract changes.
|
|
295
|
+
|
|
296
|
+
Linux ARM64 shares the implemented Linux provider, focused tests, and a
|
|
297
|
+
target-scoped remote evidence workflow. The recorded workflow exercised the
|
|
298
|
+
native AArch64 toolchain, DEB, host/Core/bridge, sandboxed WebKit readiness, and
|
|
299
|
+
owned process-group cancellation. The recorded Android development path
|
|
300
|
+
exercised physical-device build, readiness, cancellation, uninstall, and
|
|
301
|
+
absence behavior. Neither record establishes
|
|
302
|
+
production signing, installation, publishing, update continuity, release
|
|
303
|
+
acceptance, or production readiness.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Arcane application compatibility
|
|
2
|
+
|
|
3
|
+
Arcane application compatibility is a capability contract, not an exact
|
|
4
|
+
runtime-version pin. An app may run on a newer Arcane Core when the host meets
|
|
5
|
+
all of the app's declared requirements.
|
|
6
|
+
|
|
7
|
+
For a browser-only app, `permissions`, `security`, and
|
|
8
|
+
`requirements.minimumCoreVersion` may be omitted. Missing permissions normalize
|
|
9
|
+
to empty capability and method sets, and missing security normalizes to empty
|
|
10
|
+
origin declarations with optional hardening disabled. Existing explicitly
|
|
11
|
+
authored records remain unchanged.
|
|
12
|
+
|
|
13
|
+
When the selected target actually uses Arcane Core, compatibility requires:
|
|
14
|
+
|
|
15
|
+
- the requested target is declared by that app;
|
|
16
|
+
- the host Core version is greater than or equal to the explicitly declared
|
|
17
|
+
`requirements.minimumCoreVersion`;
|
|
18
|
+
- `requirements.arcaneProtocol` matches the host protocol generation;
|
|
19
|
+
- every declared `requirements.features` entry is advertised by the host;
|
|
20
|
+
- every declared `permissions.capabilities` entry is available; and
|
|
21
|
+
- every declared `permissions.methods` entry is available.
|
|
22
|
+
|
|
23
|
+
The effective Core floor for a native build is the highest minimum explicitly
|
|
24
|
+
declared by the SDK runtime, the selected app, and its complete bundled-app
|
|
25
|
+
closure. Browser-only targets do not invent a Core floor. The native build plan
|
|
26
|
+
checks every member of that closure before producing output.
|
|
27
|
+
|
|
28
|
+
This permits normal non-breaking Arcane upgrades. For example, an app requiring
|
|
29
|
+
Core `0.8.12` can run on `0.8.13` or `0.9.0` when the required protocol,
|
|
30
|
+
features, capabilities, and methods are still present. A higher version does
|
|
31
|
+
not override a missing contract.
|
|
32
|
+
|
|
33
|
+
Breaking changes must be visible at the contract boundary. A host must not
|
|
34
|
+
continue advertising an old protocol, feature, capability, or method when its
|
|
35
|
+
meaning or guarantees are no longer compatible. It must instead change the
|
|
36
|
+
protocol generation or contract identifier so the incompatibility is reported
|
|
37
|
+
before launch. Ordinary compatibility does not depend on byte counts, hashes,
|
|
38
|
+
digests, provenance receipts, or optional security declarations.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Canonical SDK events and time-travel review
|
|
2
|
+
|
|
3
|
+
`arcaneEvents` is the canonical synchronous SDK event authority. The module
|
|
4
|
+
installs or reuses one current-protocol authority at `globalThis.arcaneEvents` in
|
|
5
|
+
each JavaScript realm, even when the same source is loaded through duplicate
|
|
6
|
+
module URLs. It is not a cross-frame, worker, process, native-host, or cloud bus.
|
|
7
|
+
|
|
8
|
+
`EventManager` remains the isolated diagnostics API. `new EventManager()` and
|
|
9
|
+
`createEventManager()` each create an independent `event-pubsub` bus whose
|
|
10
|
+
`on()`, `emit()`, and `instrument()` handlers are strict: a synchronous listener
|
|
11
|
+
failure propagates to that publisher. Use `arcaneEvents.subscribe()` and
|
|
12
|
+
`createArcaneEventSource()` for canonical SDK semantic events instead.
|
|
13
|
+
|
|
14
|
+
When this module installs the authority, the global is an own, non-enumerable,
|
|
15
|
+
writable, configurable data property. The created authority exposes
|
|
16
|
+
`Symbol.for('arcane-os.arcane-events-authority')` and public `protocol` as
|
|
17
|
+
`arcane-event-authority/1`. A later import reuses a value with that protocol and
|
|
18
|
+
the required callable API. Otherwise the module installs a new authority when
|
|
19
|
+
the property can be defined; installation failure reports
|
|
20
|
+
`ARCANE_EVENT_AUTHORITY_INSTALL_FAILED`.
|
|
21
|
+
|
|
22
|
+
Import the dedicated host-neutral entry point:
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import {
|
|
26
|
+
arcaneEvents,
|
|
27
|
+
createArcaneEventSource,
|
|
28
|
+
createEventManager,
|
|
29
|
+
projectArcaneDOMEvent,
|
|
30
|
+
PLAYBACK_RECORD_EVENT
|
|
31
|
+
} from 'arcane-os/event-manager';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
An SDK publisher owns one source handle for its lifetime and declares every
|
|
35
|
+
semantic event type up front:
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
const controller={};
|
|
39
|
+
const events=createArcaneEventSource(controller,{
|
|
40
|
+
source:'app.editor',
|
|
41
|
+
eventTypes:['document.save.completed']
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const unsubscribe=arcaneEvents.subscribe('document.save.completed',occurrence=>{
|
|
45
|
+
console.info('Saved',occurrence.detail.documentId);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const publication=events.dispatch(
|
|
49
|
+
'document.save.completed',
|
|
50
|
+
{documentId:'example',document:liveDocument},
|
|
51
|
+
{
|
|
52
|
+
operationId:'save-42',
|
|
53
|
+
publicDetail:{documentId:'example'},
|
|
54
|
+
cancelable:false
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
projectArcaneDOMEvent(editorElement,publication.occurrence);
|
|
59
|
+
unsubscribe();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`createArcaneEventSource(owner,options)` is the public wrapper for
|
|
63
|
+
`arcaneEvents.createSource(owner,options)`. `options` is the closed record
|
|
64
|
+
`{source,eventTypes,onListenerError?}`. Each non-null object or function owner
|
|
65
|
+
may have one active source, and the returned handle exposes
|
|
66
|
+
`{protocol,descriptor,source,instanceId,eventTypes,disposed,subscribe,on,once,
|
|
67
|
+
addEventListener,removeEventListener,dispatch,dispatchEvent,dispose,destroy}`.
|
|
68
|
+
|
|
69
|
+
`dispatch()` synchronously delivers one mutable `arcane-event-occurrence/1`
|
|
70
|
+
to exact-type canonical subscribers, then an EventTarget-shaped view to the
|
|
71
|
+
source's own listeners. The occurrence contains `occurrenceId`, `type`, `source`,
|
|
72
|
+
`instanceId`, `operationId`, a complete plain-data snapshot in `detail`,
|
|
73
|
+
`cancelable`, live `defaultPrevented`, and `preventDefault()`. When
|
|
74
|
+
`publicDetail` is omitted, canonical detail is the normalized source detail;
|
|
75
|
+
record values merge with explicitly supplied `publicDetail`, and other
|
|
76
|
+
combinations are retained under `{compatibility,publicDetail}`. The same
|
|
77
|
+
canonical detail enters optional time-travel history.
|
|
78
|
+
|
|
79
|
+
Source listeners retain EventTarget compatibility: function listeners receive
|
|
80
|
+
the source owner as `this`, and the source event view exposes that owner as
|
|
81
|
+
both `target` and `currentTarget`. Plain records and arrays are shallow-copied;
|
|
82
|
+
rich host objects remain local and are not recursively copied.
|
|
83
|
+
EventTarget-shaped `addEventListener()` and `removeEventListener()` preserve
|
|
84
|
+
native no-op handling for null or non-listener callbacks; strict `subscribe()`
|
|
85
|
+
and `on()` still reject an invalid handler.
|
|
86
|
+
|
|
87
|
+
Canonical delivery is observational. Every active listener runs in registration
|
|
88
|
+
order. A listener failure publishes one complete
|
|
89
|
+
`arcane.event.listener.error` occurrence and is reported through `reportError`
|
|
90
|
+
or `console.error`; it does not undo committed domain work or make
|
|
91
|
+
`dispatch()` throw. An optional source `onListenerError(error,errorOccurrence)`
|
|
92
|
+
callback receives the raw failure and its canonical listener-error occurrence
|
|
93
|
+
only at that owner-local boundary; `errorOccurrence` is `null` only when the
|
|
94
|
+
secondary error occurrence itself could not be constructed. Subscriber
|
|
95
|
+
promises are not awaited, so keep completion, backpressure, and asynchronous
|
|
96
|
+
failure in the SDK-owned queue or operation that owns them. There is no second
|
|
97
|
+
Promise-returning publication bus: `dispatch()`, cancellation handling, sticky
|
|
98
|
+
state commits, and listener installation remain synchronous. Owned promises and
|
|
99
|
+
`createEventQueue()` own asynchronous work, ordering, failure, and backpressure;
|
|
100
|
+
an `AbortSignal` removes a subscription but does not claim that already-started
|
|
101
|
+
provider, host, or queue work stopped.
|
|
102
|
+
|
|
103
|
+
`arcaneEvents.subscribe(type,handler,{once=false,signal}={})` returns an
|
|
104
|
+
idempotent unsubscribe function whose `.dispose` property is the same function.
|
|
105
|
+
An already-aborted signal installs nothing, and abort removes the registration
|
|
106
|
+
deterministically. Source `on()` follows the same lifecycle. EventTarget-shaped
|
|
107
|
+
`addEventListener()`/`removeEventListener()` calls deduplicate by
|
|
108
|
+
type/listener/capture. Calling a source's idempotent `dispose()` emits its final
|
|
109
|
+
`arcane.event.source.disposed` occurrence, removes its registrations, and frees
|
|
110
|
+
the owner to register a later source.
|
|
111
|
+
|
|
112
|
+
Cancellation is synchronous and observational. For a cancelable occurrence,
|
|
113
|
+
canonical or source listeners may call `preventDefault()`; `dispatch()` then
|
|
114
|
+
returns `{occurrence,accepted:false}`. Callers decide whether cancellation gates
|
|
115
|
+
their domain operation. `projectArcaneDOMEvent()` is a one-way DOM adapter: it
|
|
116
|
+
creates one `CustomEvent`, adds the canonical identifiers to a mutable outer
|
|
117
|
+
detail object, preserves any source-detail `source` value, exposes
|
|
118
|
+
the canonical emitter as `arcaneSource`, propagates DOM cancellation back to the
|
|
119
|
+
occurrence, and never republishes the DOM event into the authority. It returns `false`
|
|
120
|
+
without dispatching when the occurrence is already canceled.
|
|
121
|
+
|
|
122
|
+
The authority also retains `on`, `once`, `off`, `reset`, `emit`, `instrument`,
|
|
123
|
+
and `forward` for direct EventManager-style diagnostics. Those handlers
|
|
124
|
+
are separate from canonical `subscribe()` registrations; `off()` and `reset()`
|
|
125
|
+
cannot remove canonical or source-owned registrations. SDK publishers use
|
|
126
|
+
source handles. AIRuntimeState consumers use the focused subscription helpers
|
|
127
|
+
or `arcaneEvents.subscribe()`.
|
|
128
|
+
|
|
129
|
+
## Authority failures
|
|
130
|
+
|
|
131
|
+
`ARCANE_EVENT_ERROR_CODES` maps every key below to the identical
|
|
132
|
+
string value. Thrown authority errors expose that value as `error.code`:
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
ARCANE_EVENT_AUTHORITY_INSTALL_FAILED
|
|
136
|
+
ARCANE_EVENT_SOURCE_INVALID
|
|
137
|
+
ARCANE_EVENT_SOURCE_ALREADY_REGISTERED
|
|
138
|
+
ARCANE_EVENT_SOURCE_DISPOSED
|
|
139
|
+
ARCANE_EVENT_SOURCE_EVENT_TYPE_UNDECLARED
|
|
140
|
+
ARCANE_EVENT_OCCURRENCE_INVALID
|
|
141
|
+
ARCANE_EVENT_OCCURRENCE_SEQUENCE_EXHAUSTED
|
|
142
|
+
ARCANE_EVENT_SOURCE_SEQUENCE_EXHAUSTED
|
|
143
|
+
ARCANE_EVENT_LISTENER_CALLBACK_FAILED
|
|
144
|
+
ARCANE_EVENT_DOM_DETAIL_COLLISION
|
|
145
|
+
ARCANE_EVENT_DOM_TARGET_INVALID
|
|
146
|
+
ARCANE_EVENT_DOM_OPTIONS_INVALID
|
|
147
|
+
ARCANE_EVENT_SUBSCRIPTION_TYPE_INVALID
|
|
148
|
+
ARCANE_EVENT_SUBSCRIPTION_HANDLER_INVALID
|
|
149
|
+
ARCANE_EVENT_SUBSCRIPTION_OPTIONS_INVALID
|
|
150
|
+
ARCANE_EVENT_SUBSCRIPTION_SIGNAL_INVALID
|
|
151
|
+
ARCANE_EVENT_DISPATCH_EVENT_INVALID
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Listener callback failure is observational: it appears as
|
|
155
|
+
`ARCANE_EVENT_LISTENER_CALLBACK_FAILED` inside the
|
|
156
|
+
`arcane.event.listener.error` occurrence. Its complete public detail is
|
|
157
|
+
`{code:'ARCANE_EVENT_LISTENER_CALLBACK_FAILED',reason:'listener-threw',
|
|
158
|
+
eventType,occurrenceId,source,instanceId,operationId,error}`. Source disposal publishes
|
|
159
|
+
`arcane.event.source.disposed` with normalized canonical detail
|
|
160
|
+
`{source,instanceId,reason:'source-disposed'}` rather than throwing from committed
|
|
161
|
+
source dispatch.
|
|
162
|
+
|
|
163
|
+
## Enable a complete event stack
|
|
164
|
+
|
|
165
|
+
Time-travel recording is disabled by default. With the flag off, the manager is
|
|
166
|
+
only a pub/sub bus: it captures no history, source stack, or DOM activity.
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
const events=createEventManager({
|
|
170
|
+
timeTravel:true,
|
|
171
|
+
dom:{root:document}
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
It can also be enabled around a diagnostic session:
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
arcaneEvents.enableTimeTravel({
|
|
179
|
+
dom:{root:document}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Exercise the scenario.
|
|
183
|
+
|
|
184
|
+
arcaneEvents.disableTimeTravel();
|
|
185
|
+
const serialized=arcaneEvents.exportStack();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
While enabled, every isolated-manager event receives a mutable
|
|
189
|
+
`arcane-event-stack/1` record containing the session and event ids, sequence,
|
|
190
|
+
UTC and monotonic timestamps, source/category, correlation and causation ids,
|
|
191
|
+
nested dispatch depth, a complete payload snapshot, completion or failure
|
|
192
|
+
outcome, and dispatch duration. Recording preserves complete strings, URLs,
|
|
193
|
+
public details, collections, object entries, nesting, and available source or
|
|
194
|
+
error stack text. It performs no implicit redaction. Do not place credentials
|
|
195
|
+
or secrets in event payloads or metadata. The durable JSON shape is published
|
|
196
|
+
as `arcane-os/schemas/event-stack.json`.
|
|
197
|
+
|
|
198
|
+
Recording retains the complete session until the caller clears history.
|
|
199
|
+
Disabling recording stops future capture without clearing existing records. It
|
|
200
|
+
never truncates, clips, tails, elides, or rotates event content. Arcane does not
|
|
201
|
+
upload or persist a stack automatically.
|
|
202
|
+
|
|
203
|
+
## DOM observation
|
|
204
|
+
|
|
205
|
+
When a DOM root is attached while time travel is enabled, capture-phase
|
|
206
|
+
listeners record the standard keyboard, pointer, mouse, touch, form, focus,
|
|
207
|
+
clipboard, drag, selection, and scroll interaction set. A `MutationObserver`
|
|
208
|
+
records attribute, text, insertion, and removal mutations, including old values
|
|
209
|
+
where the platform exposes them. Open shadow roots present at startup or found
|
|
210
|
+
in inserted nodes are observed separately; composed events are deduplicated.
|
|
211
|
+
|
|
212
|
+
DOM instrumentation preserves complete input values, node markup and text,
|
|
213
|
+
selectors, document and attribute URLs, keyboard/composition/input fields, and
|
|
214
|
+
object-valued event details. It does not trim, clip, tail, redact, or otherwise
|
|
215
|
+
shorten those values. This can include sensitive page content, so attach the
|
|
216
|
+
diagnostic only when that complete capture is intended, never place credentials
|
|
217
|
+
in the observed page or event payloads, and review recordings before sharing.
|
|
218
|
+
`captureMutations:false` disables mutation observation, and
|
|
219
|
+
`observeOpenShadowRoots:false` leaves open shadow roots outside the observer;
|
|
220
|
+
interaction events remain complete.
|
|
221
|
+
|
|
222
|
+
Mutation observation is an audit backstop, not proof of every renderer state
|
|
223
|
+
change. It cannot see closed shadow roots, cross-origin frames, external web
|
|
224
|
+
content, CSSOM/canvas drawing, most property-only writes, native/kernel activity,
|
|
225
|
+
or interactions that happened before instrumentation started. Use semantic
|
|
226
|
+
`instrument()` events at SDK-owned mutation boundaries when exact intent and
|
|
227
|
+
causation matter.
|
|
228
|
+
|
|
229
|
+
## Seek and playback
|
|
230
|
+
|
|
231
|
+
`seek(sequence)` moves the diagnostic review cursor and emits
|
|
232
|
+
`arcane.time-travel.seek`. It does not rewrite live DOM or application state.
|
|
233
|
+
The default playback mode emits each complete record on
|
|
234
|
+
`arcane.time-travel.playback.record` for a debugger or review UI:
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
events.on(PLAYBACK_RECORD_EVENT,record=>reviewTimeline(record));
|
|
238
|
+
await events.playback({stack:serialized,mode:'review',speed:2});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`speed: 0` plays immediately; a positive value preserves monotonic recorded
|
|
242
|
+
delays at that multiplier. Playback supports `AbortSignal` and emits an explicit
|
|
243
|
+
completed, cancelled, or failed terminal event. Recording is suppressed during
|
|
244
|
+
playback so replay cannot recursively add itself to the stack.
|
|
245
|
+
|
|
246
|
+
`mode: 'events'` redispatches recorded event payloads to live subscribers. That
|
|
247
|
+
mode can execute application effects and is only appropriate inside an isolated
|
|
248
|
+
diagnostic harness with effectful subscribers replaced. The SDK does not
|
|
249
|
+
synthesize trusted browser input, restore a prior DOM snapshot, resend native
|
|
250
|
+
RPC, repeat provisioning, launch processes, write storage, or repeat network or
|
|
251
|
+
other privileged effects.
|
|
252
|
+
|
|
253
|
+
## Browser delivery boundary
|
|
254
|
+
|
|
255
|
+
The package entry point works directly in Node and through browser bundlers.
|
|
256
|
+
The npm artifact bundles the exact `event-pubsub` and `strong-type` pair because
|
|
257
|
+
`event-pubsub@6.1.0` uses a sibling-relative runtime import. Unbundled browser
|
|
258
|
+
use must preserve that physical sibling layout and provide import-map entries
|
|
259
|
+
for the public SDK entry and `event-pubsub`.
|
|
260
|
+
|
|
261
|
+
The managed Arcane browser runtime ships the focused entry and its
|
|
262
|
+
dependency closure. Its import map resolves `arcane-os/event-manager` exactly;
|
|
263
|
+
query, fragment, and subpath variants are not alternate authority identities.
|