arcane-os 0.5.10 → 0.5.12

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 (54) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +117 -26
  3. package/browser-runtime/ai/browser-speech-providers.mjs +1 -1
  4. package/docs/architecture.md +303 -0
  5. package/docs/compatibility.md +38 -0
  6. package/docs/event-manager.md +263 -0
  7. package/docs/platform-targets.md +104 -0
  8. package/docs/publishing.md +126 -0
  9. package/docs/reference/README.md +206 -0
  10. package/docs/reference/ai/browser-speech.md +879 -0
  11. package/docs/reference/ai/browser-wasm.md +637 -0
  12. package/docs/reference/ai/twin-cloud.md +156 -0
  13. package/docs/reference/arcane-ollama.md +288 -0
  14. package/docs/reference/availability-and-normalization.md +224 -0
  15. package/docs/reference/behavioral-testing.md +129 -0
  16. package/docs/reference/cli.md +820 -0
  17. package/docs/reference/core/README.md +61 -0
  18. package/docs/reference/core/arcane-ai-contracts.md +906 -0
  19. package/docs/reference/core/arcane-api.md +601 -0
  20. package/docs/reference/core/arcane-entities.md +59 -0
  21. package/docs/reference/core/arcane-events.md +134 -0
  22. package/docs/reference/core/ollama-module.md +181 -0
  23. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +1909 -0
  24. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +1057 -0
  25. package/docs/reference/core/reference/arcane-api/core-and-events.md +320 -0
  26. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +610 -0
  27. package/docs/reference/core/reference/arcane-api/namespaces.md +1157 -0
  28. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +1423 -0
  29. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +315 -0
  30. package/docs/reference/event-manager.md +1409 -0
  31. package/docs/reference/inventory/package-api.json +3194 -0
  32. package/docs/reference/inventory/runtime-components.json +1015 -0
  33. package/docs/reference/inventory/runtime-entities.json +25 -0
  34. package/docs/reference/inventory/runtime-modules.json +1367 -0
  35. package/docs/reference/mail.md +309 -0
  36. package/docs/reference/protocols.md +749 -0
  37. package/docs/reference/runtime-components.md +1532 -0
  38. package/docs/reference/runtime-entities.md +305 -0
  39. package/docs/reference/runtime-modules.md +3310 -0
  40. package/docs/reference/sdk-api.md +6733 -0
  41. package/docs/roadmap.md +79 -0
  42. package/docs/work-amplification.md +66 -0
  43. package/examples/wasm-ai-demo/README.md +80 -0
  44. package/examples/wasm-ai-demo/app.js +787 -0
  45. package/examples/wasm-ai-demo/index.html +343 -0
  46. package/examples/wasm-ai-demo/profile-tools.js +217 -0
  47. package/examples/wasm-ai-demo/profiles/BOSS.Modelfile +106 -0
  48. package/examples/wasm-ai-demo/profiles/PreCrisis.Modelfile +693 -0
  49. package/examples/wasm-ai-demo/rag/boss-library.json +3006 -0
  50. package/examples/wasm-ai-demo/rag.js +295 -0
  51. package/examples/wasm-ai-demo/server.mjs +71 -0
  52. package/package.json +10 -1
  53. package/runtime/arcane/modules/AI.js +60 -11
  54. package/runtime/arcane/modules/AIProviderRuntime.js +26 -5
@@ -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.
@@ -0,0 +1,104 @@
1
+ # Platform target contract
2
+
3
+ Every target adapter implements protocol `arcane-target-adapter/1` with these
4
+ named operations:
5
+
6
+ ```text
7
+ describe -> doctor -> prepare -> plan -> build -> run
8
+ ```
9
+
10
+ The available browser adapter plans from the selected workspace and schema-1
11
+ release manifest. The SDK also implements the process-local
12
+ `arcane-native-build-plan/1` and `arcane-native-builder/1` boundary for an
13
+ explicitly injected provider. It selects an app release and schema-2 descriptor,
14
+ toolchain, platform, architecture, format, signing mode, declared dependency
15
+ releases, and destination. Verification is a separate operation only when the
16
+ user explicitly selects it for the release artifact.
17
+
18
+ Native targets are available by explicitly pairing the SDK with fixed provider
19
+ modules in a compatible Arcane OS checkout. Every native request also requires
20
+ the canonical app descriptor to declare the exact target selected on the
21
+ command line. The SDK package does not silently search for a toolchain, infer a
22
+ descriptor target, embed the Arcane machine bundle, or substitute browser
23
+ output. For example:
24
+
25
+ ```bash
26
+ # Choose one target when creating each app repository.
27
+ npx arcane-os@dev new my-app --path ./my-app --target portable --git
28
+ cd my-app
29
+ npm install
30
+ npm exec -- arcane native-doctor --target portable --arcane-root "../Arcane OS"
31
+ npm exec -- arcane build --target portable --arcane-root "../Arcane OS"
32
+
33
+ # In an app scaffolded with --target windows-x64:
34
+ npm exec -- arcane build --target windows-x64 --arcane-root "../Arcane OS"
35
+ npm exec -- arcane run --target windows-x64 --arcane-root "../Arcane OS"
36
+
37
+ # In an app scaffolded with --target linux-x64:
38
+ npm exec -- arcane build --target linux-x64 --arcane-root "../Arcane OS"
39
+ npm exec -- arcane run --target linux-x64 --arcane-root "../Arcane OS"
40
+
41
+ # In an app scaffolded with --target linux-arm64, on native ARM64 Linux:
42
+ npm exec -- arcane native-doctor --target linux-arm64 --arcane-root "../Arcane OS" --format deb --signing unsigned-local-test
43
+ npm exec -- arcane build --target linux-arm64 --arcane-root "../Arcane OS" --format deb --signing unsigned-local-test
44
+ npm exec -- arcane run --target linux-arm64 --arcane-root "../Arcane OS" --format deb --signing unsigned-local-test
45
+
46
+ # In an app scaffolded with --target android-arm64. The run command requires
47
+ # one connected physical Android device with native ARM64 support:
48
+ npm exec -- arcane native-doctor --target android-arm64 --arcane-root "../Arcane OS" --format apk --signing development
49
+ npm exec -- arcane build --target android-arm64 --arcane-root "../Arcane OS" --format apk --signing development
50
+ npm exec -- arcane run --target android-arm64 --arcane-root "../Arcane OS" --format apk --signing development
51
+ ```
52
+
53
+ Every native scaffold also declares the browser target, so one repository can
54
+ use the normal browser development loop and its one selected native build. It
55
+ includes the raster icon required by the current native platform. Use the
56
+ matching scaffold target (`portable`, `windows-x64`, `linux-x64`, `linux-arm64`,
57
+ or `android-arm64`) before running the corresponding command.
58
+
59
+ `native-prepare` remains a standalone diagnostic. The normal build recipe omits
60
+ it and lets `build` prepare the selected toolchain state.
61
+
62
+ The portable output is an app-scoped Arcane Core directory. It is an explicit
63
+ portable builder payload, not an executable, and it has no direct run operation.
64
+ The external workspace defaults to `build/portable/`; integrated Arcane work
65
+ must use the same canonical checkout for `--workspace` and `--arcane-root`, and
66
+ must name an `--output-root` outside that checkout.
67
+
68
+ Compatibility uses the highest minimum Core version declared by the SDK runtime,
69
+ selected app, and bundled app dependencies, plus each app's Arcane protocol and
70
+ required features, capabilities, and methods. Newer Core versions are accepted
71
+ when those contracts remain available. See [compatibility.md](compatibility.md)
72
+ for the complete compatibility and breaking-change rule.
73
+
74
+ | Target | Formats | Development status |
75
+ |---|---|---|
76
+ | `browser` | `directory` | Available |
77
+ | `portable` | `portable` directory | Available with explicit `--arcane-root`; not executable |
78
+ | `windows-x64` | `exe` bundle | Available with explicit `--arcane-root`; unsigned local development only |
79
+ | `linux-x64` | `deb` | Available with explicit `--arcane-root`; unsigned local development only |
80
+ | `linux-arm64` | `deb` | Available with explicit `--arcane-root` on a compatible native ARM64 toolchain; unsigned local development only |
81
+ | `android-arm64` | `apk` | Available with explicit `--arcane-root`; development-signed, architecture-neutral, and physical/native ARM64 for run |
82
+
83
+ Every native target accepts one selected app release and its complete bundled
84
+ dependency closure through the provider boundary. The providers retain the
85
+ toolchain state required for build and, where supported, launch; app source and
86
+ workspace paths are not supplied to the provider. Linux run extracts to a
87
+ user-owned development tree without package installation or elevation.
88
+
89
+ Linux ARM64 uses the implemented Linux provider and is available only with a
90
+ compatible native ARM64 toolchain. The recorded target-scoped workflow built a
91
+ native ARM64 DEB, exercised the AArch64 host/Core/bridge, reached WebKit readiness,
92
+ and drained the owned process group. It loaded Ubuntu's packaged Bubblewrap
93
+ AppArmor profile while leaving the global user-namespace restriction enabled.
94
+ Android produces one development-signed APK with no native library or
95
+ ABI-specific payload. The APK is therefore architecture-neutral, while
96
+ `arcane run --target android-arm64` deliberately requires a physical device
97
+ with native ARM64 support. The recorded development path exercised physical
98
+ ARM64 build, readiness, cancellation, uninstall, and absence behavior. Both records
99
+ are development evidence, not production readiness.
100
+
101
+ Android AAB output, release signing, store publishing, and update continuity are
102
+ deferred. Windows and Linux production signing, installation, and update
103
+ acceptance also remain separate promotion work. The SDK never copies
104
+ proprietary application source into the Arcane checkout to bypass the boundary.
@@ -0,0 +1,126 @@
1
+ # npm publication
2
+
3
+ ## Canonical main and npm channels
4
+
5
+ `main` is the single canonical working and publication branch before and after
6
+ the first release. Do not create a development branch. `-dev` versions select
7
+ the npm `dev` dist-tag, while bare numeric stable versions select
8
+ `latest`. These are registry channels, not Git branches.
9
+
10
+ ## Stable and development npm publication
11
+
12
+ The package version and `publishConfig.tag` must agree exactly: `-dev` uses
13
+ `dev`, and a bare numeric stable version uses `latest`. npm is the canonical
14
+ SDK distribution: application repositories add an exact `arcane-os` project
15
+ dependency and invoke its local CLI with `npm exec -- arcane`. A separate
16
+ global installer, standalone SDK executable, NuGet package, Homebrew formula,
17
+ or OS package is not part of this release surface.
18
+
19
+ Publication checks run only after the user explicitly selects an npm release.
20
+ That selected-release workflow validates package metadata, the executable and
21
+ `.gitattributes` boundary, the complete package inventory, version/channel
22
+ agreement, and required license notices. One unprivileged producer packs one
23
+ `.tgz` under the selected Node and npm versions and uploads it as one Actions
24
+ artifact with a recorded run id, artifact id, version, and source commit. It
25
+ does not impose byte counts, hashes, digests, provenance receipts, or unrelated
26
+ test suites as ordinary development gates. Broader integration, regression,
27
+ platform, browser, presentation, and documentation work remains separately
28
+ user selected.
29
+
30
+ `publish-dev.yml` can run only when manually dispatched from `main` in
31
+ `TheWizardNexus/arcane-os-sdk`. Dispatch supplies the exact successful Check
32
+ run id, artifact id, and numeric version. The workflow downloads that exact Check
33
+ artifact, derives `dev` or `latest` from its version, and publishes the selected
34
+ `.tgz`. It may check out current source only for the publication controller; it
35
+ never repacks current source and never invokes `npm pack` or `npm publish .`
36
+ under publication authority. A
37
+ repository-wide concurrency group prevents simultaneous publication jobs;
38
+ GitHub may replace an older pending dispatch, and each surviving dispatch is
39
+ safe to rerun. Preflight rejects tag rollback, malformed registry state, or any
40
+ dist-tag other than `dev` and `latest`; an already-published matching version
41
+ is an idempotent success. Post-publication status preserves the other channel
42
+ and reports npm's response. It tolerates npm's publish-time scanning. If
43
+ scanning or manual review remains pending, the workflow reports that state and
44
+ a rerun safely resumes without republishing the version.
45
+
46
+ The public `0.3.2` release is fixed to package-source commit
47
+ `445bd2d982f12e6ef8dd2b615c70512000cc5224`, selected Check run
48
+ `33264677687`, and publication/registry run `33264829711`. Its numeric Git tag
49
+ and GitHub release title are both `0.3.2`. Later documentation or example
50
+ commits do not replace that package authority.
51
+
52
+ The unscoped package installs both `arcane` and `arcane-os`. The short command
53
+ is the documented default; `arcane-os` is the collision-safe fallback. npm
54
+ package names are unique, but executable names are not globally reserved.
55
+
56
+ When `npm view arcane-os@dev version` reports the package unavailable, run
57
+ `npm run pack:local` in this SDK checkout for local development, scaffold with
58
+ `node ./bin/arcane.mjs new ...`, and install the resulting `.tgz` into the app
59
+ with `npm install --save-dev --save-exact <path>`. Keep the tarball at the path
60
+ recorded by `package-lock.json`; subsequent `npm ci` uses that declared package.
61
+ Arcane reads the installed package's name and version against the root
62
+ dependency declaration. A local directory `file:` install is intentionally unsupported because
63
+ it may be linked.
64
+
65
+ The npm package already has its trusted-publishing relationship. Each later
66
+ release therefore follows the same direct selected-artifact path: push the
67
+ intended `main` source, manually run Check for that exact revision, review the
68
+ resulting package inventory and legal notices, then manually dispatch
69
+ publication with that Check run and artifact. Confirm the selected version and
70
+ dist-tag after publication. Never rebuild or repack the artifact under
71
+ publication authority, and never substitute a different source revision.
72
+
73
+ Generated app CI uses `npm ci --ignore-scripts`, so its lock must exist and its
74
+ dependency source must be reachable by the runner. A sibling local tarball is a
75
+ workstation workflow, not a portable GitHub dependency source; switch to the
76
+ exact registry release (or deliberately vendor the tarball) before remote CI.
77
+
78
+ ## Reusable application release workflow
79
+
80
+ The checked-in reusable workflow is not an ordinary supported release path
81
+ until its implementation matches the governing contract below.
82
+
83
+ External app repositories can call `.github/workflows/release-app.yml` from a
84
+ selected SDK repository revision. The reusable workflow checks out the selected
85
+ caller commit, installs only the caller's committed dependency lock, packages,
86
+ bundles, and uploads one explicitly selected app. Any tests, checks, or artifact
87
+ verification run only because that release output was explicitly selected.
88
+ The workflow never publishes npm, creates a GitHub Release, loops across apps,
89
+ or changes Arcane runtime policy.
90
+
91
+ The one build job holds only `contents: read`. It uses the caller's normal
92
+ locked installation, runs one selected `arcane package`, creates one selected
93
+ `arcane bundle`, and uploads that complete bundle. It creates no hashes, byte
94
+ identities, receipts, provenance records, or attestation sidecars and does not
95
+ run a second admission job.
96
+
97
+ Stable versioning, the npm `latest` tag, and an official GitHub release remain a
98
+ separate explicit release decision. Current `main` development does not
99
+ silently convert a `-dev` package into an official release. A stable release
100
+ must publish the exact selected Check artifact under `latest`; GitHub may then
101
+ attach that same package. Its Git
102
+ tag and GitHub release title must both be the same bare numeric
103
+ `MAJOR.MINOR.PATCH`. Prerelease versions do not get a misleading numeric
104
+ GitHub release, and no release creates a Git branch for an npm dist-tag.
105
+
106
+ ## Documentation publication
107
+
108
+ Documentation publication occurs only when the user explicitly selects it. The
109
+ Pages job checks out that selected `main` revision without persistent
110
+ credentials and uploads only the static `site/` tree. It does not automatically
111
+ run the SDK test suite, checks, generators, or repository build code.
112
+
113
+ The deployment job holds only the read, Pages, and OIDC permissions required by
114
+ that selected artifact. The `github-pages` environment remains the final
115
+ deployment authority. Documentation channels are post-registry presentation
116
+ work and do not change the canonical source branch.
117
+
118
+ ## Work-amplification record
119
+
120
+ The release graph is one selected `main` revision and one npm release candidate.
121
+ One producer creates the tarball. Publication names that producer's exact Check
122
+ run, artifact, and version and does not rebuild from a later checkout. The
123
+ release workflow checks only the publication contract and required legal
124
+ inventory for that selected output.
125
+ Platform matrices, full product regressions, Pages, and broader presentation
126
+ work remain separate user-selected operations.