arcane-os 0.56.0 → 0.58.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 (75) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +6 -2
  3. package/browser-runtime/ai/core-local.mjs +306 -0
  4. package/browser-runtime/ai/core-onnx.mjs +96 -0
  5. package/browser-runtime/ai/onnx-tensors.mjs +85 -0
  6. package/browser-runtime/core/client.mjs +151 -16
  7. package/docs/architecture.md +5 -2
  8. package/docs/platform-targets.md +30 -13
  9. package/docs/reference/README.md +38 -3
  10. package/docs/reference/availability-and-normalization.md +9 -6
  11. package/docs/reference/cli.md +29 -9
  12. package/docs/reference/core-client.md +80 -0
  13. package/docs/reference/core-native-packaging.md +304 -12
  14. package/docs/reference/core-preferences.md +49 -0
  15. package/docs/reference/diarization.md +206 -0
  16. package/docs/reference/git-text-snapshot.md +104 -0
  17. package/docs/reference/inventory/package-api.json +330 -22
  18. package/docs/reference/local-ai.md +331 -0
  19. package/docs/reference/protocols.md +97 -20
  20. package/docs/reference/pwa.md +5 -2
  21. package/docs/reference/runtime-modules.md +6 -5
  22. package/docs/reference/sdk-api.md +611 -63
  23. package/package.json +15 -3
  24. package/runtime/arcane/modules/LocalAIReadiness.js +3 -1
  25. package/schemas/arcane-app.schema.json +55 -1
  26. package/schemas/arcane-package.schema.json +44 -0
  27. package/schemas/native-build-plan.schema.json +27 -1
  28. package/schemas/target-adapter.schema.json +2 -0
  29. package/src/app-descriptor.mjs +18 -2
  30. package/src/cli/main.mjs +20 -4
  31. package/src/constants.mjs +2 -0
  32. package/src/core/host.mjs +23 -0
  33. package/src/core/hosts/macos/ArcaneCoreProcess.h +85 -0
  34. package/src/core/hosts/macos/ArcaneCoreProcess.m +357 -0
  35. package/src/core/hosts/macos/ArcaneHost.h +86 -0
  36. package/src/core/hosts/macos/ArcaneHost.m +455 -0
  37. package/src/core/hosts/macos/ArcaneLauncher.m +432 -0
  38. package/src/core/hosts/windows/ArcaneCoreProcess.cs +3 -3
  39. package/src/core/hosts/windows/ArcaneHost.cs +695 -0
  40. package/src/core/hosts/windows/ArcaneHost.manifest +22 -0
  41. package/src/core/hosts/windows/ArcaneLauncher.cs +239 -0
  42. package/src/core/services/local-ai.mjs +621 -0
  43. package/src/core/services/packaged-web.mjs +89 -0
  44. package/src/core/services/preferences.mjs +201 -0
  45. package/src/core-classic-source.mjs +2 -2
  46. package/src/dev-server.mjs +9 -5
  47. package/src/diarization/build.mjs +35 -0
  48. package/src/diarization/index.mjs +432 -0
  49. package/src/diarization/native/CMakeLists.txt +9 -0
  50. package/src/diarization/native/main.cpp +269 -0
  51. package/src/diarization/service.mjs +129 -0
  52. package/src/git-text-snapshot.mjs +265 -0
  53. package/src/import-map.mjs +2 -0
  54. package/src/index.mjs +1 -0
  55. package/src/local-ai/archive.mjs +52 -0
  56. package/src/local-ai/config.mjs +62 -0
  57. package/src/local-ai/dev.mjs +390 -0
  58. package/src/local-ai/discover.mjs +71 -0
  59. package/src/local-ai/http.mjs +106 -0
  60. package/src/local-ai/install.mjs +459 -0
  61. package/src/local-ai/onnx-worker.mjs +85 -0
  62. package/src/local-ai/onnx.mjs +368 -0
  63. package/src/local-ai/server.mjs +262 -0
  64. package/src/native/macos-provider.mjs +291 -0
  65. package/src/native/portable-layout.mjs +37 -4
  66. package/src/native/portable-provider.mjs +44 -8
  67. package/src/native/windows-provider.mjs +262 -0
  68. package/src/native-plan.mjs +9 -1
  69. package/src/native-provider-loader.mjs +10 -2
  70. package/src/packager/core.mjs +6 -2
  71. package/src/process.mjs +184 -20
  72. package/src/scaffold.mjs +1 -1
  73. package/src/targets/index.mjs +11 -1
  74. package/src/templates/workspace-template.mjs +6 -5
  75. package/src/toolchain.mjs +33 -5
@@ -14,6 +14,7 @@ export function createCoreClient({
14
14
  eventOwnerReady,
15
15
  autoConnect=true,
16
16
  replayRuntimeState=false,
17
+ webKitDocumentLifecycle=false,
17
18
  onError=error=>global.console?.error('Arcane Core client failed.',error)
18
19
  }={}){
19
20
  const pending=new Map();
@@ -29,6 +30,7 @@ export function createCoreClient({
29
30
  let eventOwnerFailure=null;
30
31
  let transportFailure=null;
31
32
  let transportFailureReported=false;
33
+ let webKitDocument=null;
32
34
 
33
35
  function report(error){
34
36
  if(error===transportFailure){
@@ -67,8 +69,13 @@ export function createCoreClient({
67
69
  report(eventOwnerFailure);
68
70
  });
69
71
 
70
- function emit(event,data){
71
- withEvents(()=>source.dispatch(CORE_EVENT,{event,data}));
72
+ function acceptsNativeDelivery(activation){
73
+ return !closed&&(!webKitDocument||webKitDocument.current(activation));
74
+ }
75
+ function emit(event,data,activation=webKitDocument?.activation){
76
+ withEvents(function deliverEvent(){
77
+ if(acceptsNativeDelivery(activation))source.dispatch(CORE_EVENT,{event,data});
78
+ });
72
79
  }
73
80
  function complete(event,data){
74
81
  if(completedEvents.has(event))return false;
@@ -110,13 +117,23 @@ export function createCoreClient({
110
117
  if(typeof listener!=='function')throw new TypeError('Arcane event listener must be a function.');
111
118
  if(!completedEvents.has(event))return events.once(event,listener);
112
119
  const value=completedEvents.get(event);
120
+ const activation=webKitDocument?.activation;
113
121
  let active=!closed;
114
- Promise.resolve().then(function replayReadyEvent(){
115
- if(!active||closed)return;
122
+ let dispose=null;
123
+ function deliverReadyEvent(ready){
124
+ if(!active)return;
116
125
  active=false;
117
- try{listener(value);}catch(error){report(error);}
126
+ dispose?.();
127
+ try{listener(ready);}catch(error){report(error);}
128
+ }
129
+ // A ready-state subscription survives a retirement that happens
130
+ // before its queued replay, just like an ordinary registration.
131
+ if(webKitDocument)dispose=events.once(event,deliverReadyEvent);
132
+ Promise.resolve().then(function replayReadyEvent(){
133
+ if(!active||!acceptsNativeDelivery(activation))return;
134
+ deliverReadyEvent(value);
118
135
  });
119
- return function unsubscribe(){active=false;};
136
+ return function unsubscribe(){active=false;dispose?.();};
120
137
  },
121
138
  completed(event){return CORE_READY_EVENTS.includes(event)&&completedEvents.has(event);}
122
139
  };
@@ -131,8 +148,8 @@ export function createCoreClient({
131
148
  else request.resolve(result);
132
149
  return true;
133
150
  }
134
- function receive(input){
135
- if(closed)return false;
151
+ function receive(input,activation){
152
+ if(!acceptsNativeDelivery(activation))return false;
136
153
  let message=input;
137
154
  if(typeof message==='string'){
138
155
  try{message=JSON.parse(message);}
@@ -149,7 +166,9 @@ export function createCoreClient({
149
166
  // Final responses follow earlier event deliveries, including while a
150
167
  // classic host is connecting the shared SDK event owner. A stream's
151
168
  // completion must not remove its subscription before its chunks arrive.
152
- withEvents(()=>settle(message.id,message.ok?null:new CoreError(message.error),message.result));
169
+ withEvents(function deliverResponse(){
170
+ if(acceptsNativeDelivery(activation))settle(message.id,message.ok?null:new CoreError(message.error),message.result);
171
+ });
153
172
  return true;
154
173
  }
155
174
  function installCallback(name,value){
@@ -182,6 +201,107 @@ export function createCoreClient({
182
201
  catch(error){record.reject(error);}
183
202
  return true;
184
203
  }
204
+ function createWebKitDocumentTransport(webkit) {
205
+ let activation = null;
206
+ let active = false;
207
+ let registration = null;
208
+ function current(candidate) {
209
+ return !closed && active && candidate === activation;
210
+ }
211
+ function inactive() {
212
+ return new CoreError(
213
+ {code: 'ARCANE_WEBKIT_DOCUMENT_INACTIVE', message: 'This document activation no longer owns the native connection.'}
214
+ );
215
+ }
216
+ async function post(record) {
217
+ parseAcknowledgement(
218
+ await webkit.postMessage(record), {required: true}
219
+ );
220
+ }
221
+ function activate(restored = false) {
222
+ if (closed || active) return;
223
+ activation = uuid();
224
+ active = true;
225
+ const candidate = activation;
226
+ // Only transport ingress waits for native attachment. Rendering and
227
+ // the synchronous facade remain independent of this acknowledgement.
228
+ registration = Promise.resolve().then(
229
+ function announceDocument() {
230
+ if (!current(candidate)) throw inactive();
231
+ return post(
232
+ {type: 'activate', activation: candidate}
233
+ );
234
+ }
235
+ );
236
+ complete(
237
+ 'transport.ready', {protocol: CORE_PROTOCOL, transport: 'webkitgtk'}
238
+ );
239
+ registration.then(
240
+ function replayDocumentState() {
241
+ if (current(candidate) && (restored || replayRuntimeState)) {
242
+ sendControl(
243
+ {protocol: CORE_PROTOCOL, type: 'control', control: 'runtime.replay'}
244
+ );
245
+ }
246
+ }
247
+ ).catch(report);
248
+ }
249
+ function retire() {
250
+ if (!active) return false;
251
+ const candidate = activation;
252
+ // Invalidate delivery synchronously, including callbacks queued in
253
+ // WebKit or waiting for the shared event owner. Subscriptions live
254
+ // with this document and remain registered across restoration.
255
+ active = false;
256
+ completedEvents.clear();
257
+ for (const [id, request] of pending) settle(id, aborted(request.method));
258
+ const json = JSON.stringify(
259
+ {protocol: CORE_PROTOCOL, type: 'control', control: 'requests.cancelAll'}
260
+ );
261
+ post(
262
+ {type: 'retire', activation: candidate, json}
263
+ ).catch(report);
264
+ return true;
265
+ }
266
+ function restoredDocument(event) {
267
+ if (event.persisted) activate(true);
268
+ }
269
+ if (typeof global.addEventListener === 'function') {
270
+ global.addEventListener(
271
+ 'pageshow', restoredDocument, {capture: true}
272
+ );
273
+ cleanups.push(
274
+ function removeDocumentRestoration() {
275
+ global.removeEventListener(
276
+ 'pageshow', restoredDocument, {capture: true}
277
+ );
278
+ }
279
+ );
280
+ }
281
+ cleanups.push(
282
+ function releaseDocument() { active = false; }
283
+ );
284
+ installCallback('__arcaneWebKitDocumentCurrent', current);
285
+ webKitDocument = {current, activate, retire, get activation() { return active ? activation : null; }};
286
+ return {
287
+ name: 'webkitgtk',
288
+ async send(frame) {
289
+ const candidate = activation;
290
+ if (!current(candidate)) throw inactive();
291
+ const json = JSON.stringify(frame);
292
+ await registration;
293
+ // A page may retire while native attachment is pending. It
294
+ // must never submit its queued request after that retirement.
295
+ if (!current(candidate)) throw inactive();
296
+ // Abort, timeout or cancelAll may also end a request while
297
+ // this activation remains live. Unsent work stays cancelled.
298
+ if (frame.type === 'request' && !pending.has(frame.id)) return;
299
+ await post(
300
+ {type: 'frame', activation: candidate, json}
301
+ );
302
+ }
303
+ };
304
+ }
185
305
  function chooseTransport(){
186
306
  const webview=global.chrome?.webview;
187
307
  if(webview?.hostObjects){
@@ -204,6 +324,12 @@ export function createCoreClient({
204
324
  const webkit=global.webkit?.messageHandlers?.arcane;
205
325
  if(typeof global.__arcaneWebKitPostMessage==='function'||webkit){
206
326
  installCallback('__arcaneReceive',receive);
327
+ if(webKitDocumentLifecycle){
328
+ if(typeof webkit?.postMessage!=='function'){
329
+ throw new CoreError({code:'ARCANE_TRANSPORT_INVALID',message:'WebKit document lifecycle requires the arcane message handler with replies.'});
330
+ }
331
+ return createWebKitDocumentTransport(webkit);
332
+ }
207
333
  installCallback('__arcaneWebKitAcknowledge',acknowledge);
208
334
  return {name:'webkitgtk',async send(frame){
209
335
  const serialized=JSON.stringify(frame);
@@ -293,8 +419,9 @@ export function createCoreClient({
293
419
  throw error;
294
420
  }
295
421
  if(closed)throw transportFailure??new CoreError({code:'ARCANE_CLIENT_CLOSED',message:'The Core client is closed.'});
422
+ if(webKitDocument)webKitDocument.activate();
296
423
  complete('transport.ready',{protocol:CORE_PROTOCOL,transport:transport.name});
297
- if(replayRuntimeState&&!closed)sendControl({protocol:CORE_PROTOCOL,type:'control',control:'runtime.replay'});
424
+ if(replayRuntimeState&&!closed&&!webKitDocument)sendControl({protocol:CORE_PROTOCOL,type:'control',control:'runtime.replay'});
298
425
  // A native callback may close the client synchronously during replay.
299
426
  if(closed)throw transportFailure??new CoreError({code:'ARCANE_CLIENT_CLOSED',message:'The Core client is closed.'});
300
427
  return transport;
@@ -305,7 +432,7 @@ export function createCoreClient({
305
432
  :typeof global.__arcaneWebKitPostMessage==='function'||global.webkit?.messageHandlers?.arcane?'webkitgtk'
306
433
  :typeof global.arcaneAndroid?.postMessage==='function'?'android-webview'
307
434
  :global.__ARCANE_DEV_HTTP__?'development-http':'standalone');
308
- return {connected:transport!==null&&!closed,transport:name,
435
+ return {connected:transport!==null&&!closed&&(!webKitDocument||webKitDocument.activation!==null),transport:name,
309
436
  native:['webview2','webkitgtk','android-webview'].includes(name),
310
437
  managedLocalAI:['webview2','webkitgtk'].includes(name)};
311
438
  }
@@ -389,18 +516,23 @@ export function createCoreClient({
389
516
  function close(){
390
517
  if(closed)return false;
391
518
  closed=true;
392
- cancelAll();
519
+ if(webKitDocument)webKitDocument.retire();
520
+ else cancelAll();
393
521
  disposeTransport(new CoreError({code:'ARCANE_CLIENT_CLOSED',message:'The Core client is closed.'}));
394
522
  return true;
395
523
  }
524
+ function documentHidden(){
525
+ if(webKitDocument)webKitDocument.retire();
526
+ else cancelAll();
527
+ }
396
528
  if(typeof global.addEventListener==='function'){
397
- global.addEventListener('pagehide',cancelAll,{capture:true});
398
- cleanups.push(()=>global.removeEventListener('pagehide',cancelAll,{capture:true}));
529
+ global.addEventListener('pagehide',documentHidden,{capture:true});
530
+ cleanups.push(()=>global.removeEventListener('pagehide',documentHidden,{capture:true}));
399
531
  }
400
532
  if(autoConnect){
401
533
  try{connect();}catch(error){if(error.code!=='ARCANE_TRANSPORT_UNAVAILABLE')report(error);}
402
534
  }
403
- return {protocol:CORE_PROTOCOL,Error:CoreError,invoke,receive,connect,close,failTransport,cancelAll,events,eventsReady,runtime:{current:runtimeSnapshot},uuid};
535
+ return {protocol:CORE_PROTOCOL,Error:CoreError,invoke,receive,connect,close,failTransport,cancelAll,acceptsNativeDelivery,events,eventsReady,runtime:{current:runtimeSnapshot},uuid};
404
536
  }
405
537
 
406
538
  /** Existing namespace call shapes; method implementations remain host-owned. */
@@ -512,7 +644,10 @@ export function installCoreClient(global=globalThis,options={}){
512
644
  const previous=global.__arcaneReceive;
513
645
  global.__arcaneReceive=client.receive;
514
646
  const previousFailure=global.__arcaneTransportFailed;
515
- function nativeTransportFailed(error){return client.failTransport(error);}
647
+ function nativeTransportFailed(error,activation){
648
+ if(!client.acceptsNativeDelivery(activation))return false;
649
+ return client.failTransport(error);
650
+ }
516
651
  global.__arcaneTransportFailed=nativeTransportFailed;
517
652
  const close=client.close;
518
653
  const failTransport=client.failTransport;
@@ -191,13 +191,16 @@ redirect listener, defaulting to an OS-assigned port. Existing raw `tls` inputs
191
191
  retain their native HTTPS transport under the SDK, as described by the module's
192
192
  advanced TLS extension guidance; all content uses its public serving methods.
193
193
 
194
- Explicit `arcane dev --http` or source API `http:true` selects the module's
194
+ Explicit `arcane dev --http` or API `http:true` selects the module's
195
195
  single HTTP listener on `port`. It skips certificate resolution and serves the
196
196
  same selected source mappings, generated PWA routes, and conditional responses.
197
+ In API packaged mode, it serves the complete selected packaged web root and
198
+ its declared application start URL instead of source mappings.
197
199
  No HTTPS listener or redirect is started in this mode. Listener readiness,
198
200
  failure, cancellation and shutdown retain the same operation owner; reported
199
201
  URLs use the actual HTTP protocol and bound port. Browser secure-context
200
- requirements remain browser-owned. Packaged previews retain HTTPS.
202
+ requirements remain browser-owned. Source and packaged modes retain HTTPS
203
+ when `http:true` is not selected; a certificate error never switches transport.
201
204
 
202
205
  Development is an intentionally fast feedback loop. Keep each increment small
203
206
  and independently understandable so its effect has one clear cause and a
@@ -16,10 +16,15 @@ toolchain, platform, architecture, format, signing mode, declared dependency
16
16
  releases, and destination. Verification is a separate operation only when the
17
17
  user explicitly selects it for the release artifact.
18
18
 
19
- The portable target pairs with the installed SDK provider by default. An explicit
20
- `--arcane-root` retains fixed-provider selection from an Arcane OS checkout;
21
- Windows, Linux and Android executable targets still require that override and
22
- their platform toolchains. Every native request also requires
19
+ The portable, Windows x64 and macOS targets pair with installed SDK providers by
20
+ default. Windows uses the numeric SDK release's precompiled WebView2/SEA host.
21
+ macOS source composition selects that version's architecture-specific AppKit,
22
+ WebKit and bundled Node host asset; actual asset publication and Mac execution
23
+ are separate release evidence, not implied by the target registry.
24
+ An explicit `--arcane-root` retains fixed-provider selection for the registered
25
+ portable, Windows, Linux and Android checkout targets. macOS uses the installed
26
+ SDK provider and has no checkout override. Linux and Android still require that
27
+ override and their platform toolchains. Every native request also requires
23
28
  the canonical app descriptor to declare the exact target selected on the
24
29
  command line. The SDK package does not silently search for a toolchain, infer a
25
30
  descriptor target, embed the Arcane machine bundle, or substitute browser
@@ -35,8 +40,8 @@ npm exec -- arcane native-doctor --target portable
35
40
  npm exec -- arcane build --target portable
36
41
 
37
42
  # In an app scaffolded with --target windows-x64:
38
- npm exec -- arcane build --target windows-x64 --arcane-root "../Arcane OS"
39
- npm exec -- arcane run --target windows-x64 --arcane-root "../Arcane OS"
43
+ npm exec -- arcane build --target windows-x64
44
+ npm exec -- arcane run --target windows-x64
40
45
 
41
46
  # In an app scaffolded with --target linux-x64:
42
47
  npm exec -- arcane build --target linux-x64 --arcane-root "../Arcane OS"
@@ -62,7 +67,7 @@ from its installed npm dependency. After `npm install`, run
62
67
  browser maps are present. The initial scaffold reports that map as pending while
63
68
  the SDK dependency is absent. The scaffold includes the raster icon required
64
69
  by the current native platform. Use the
65
- matching scaffold target (`portable`, `windows-x64`, `linux-x64`, `linux-arm64`,
70
+ matching scaffold target (`portable`, `windows-x64`, `macos-arm64`, `macos-x64`, `linux-x64`, `linux-arm64`,
66
71
  or `android-arm64`) before running the corresponding command.
67
72
 
68
73
  `native-prepare` remains a standalone diagnostic. The normal build recipe omits
@@ -72,7 +77,8 @@ The portable output is an app-scoped payload directory with complete selected
72
77
  app and dependency files, a generated Core entry and classic client source.
73
78
  It is not an executable and has no direct run operation. Explicit service
74
79
  composition uses `createPortableNativeProvider({services:[{module,options}]})`;
75
- the default adds no OS or application services. See
80
+ the default uses an explicit descriptor service selection when supplied and
81
+ does not discover or copy OS product services. See
76
82
  [Core native packaging](reference/core-native-packaging.md).
77
83
  The external workspace defaults to `build/portable/`. Integrated Arcane work
78
84
  must name an `--output-root` outside that checkout. Explicit checkout providers
@@ -89,19 +95,30 @@ for the complete compatibility and breaking-change rule.
89
95
  |---|---|---|
90
96
  | `browser` | `directory` | Available |
91
97
  | `portable` | `portable` directory | SDK package provider by default; explicit checkout override retained; not executable |
92
- | `windows-x64` | `exe` bundle | Available with explicit `--arcane-root`; unsigned local development only |
98
+ | `windows-x64` | `exe` bundle | SDK package provider and matching precompiled release host by default; explicit checkout override retained |
99
+ | `macos-arm64` | `.app` bundle | SDK provider source; needs a matching selected or published Apple silicon host asset |
100
+ | `macos-x64` | `.app` bundle | SDK provider source; needs a matching selected or published Intel host asset |
93
101
  | `linux-x64` | `deb` | Available with explicit `--arcane-root`; unsigned local development only |
94
102
  | `linux-arm64` | `deb` | Available with explicit `--arcane-root` on a compatible native ARM64 toolchain; unsigned local development only |
95
103
  | `android-arm64` | `apk` | Available with explicit `--arcane-root`; development-signed, architecture-neutral, and physical/native ARM64 for run |
96
104
 
97
105
  macOS can consume browser applications and portable JavaScript capabilities
98
- within their declared runtimes. The current target registry has no macOS native
99
- package adapter, and the portable CLI request currently selects only Windows
100
- or Linux. macOS native packaging and Android host adaptation remain incomplete;
101
- the SDK portable payload does not supply executable hosts. A source-development
106
+ within their declared runtimes. The native target registry includes separate
107
+ Apple silicon and Intel `.app` compositions; portable CLI requests also accept
108
+ macOS. A Mac provider preserves the complete portable payload under its bundle's
109
+ Resources directory and composes the SDK host separately. A source-development
102
110
  native wrapper is also not an exposed `arcane dev` target. Native `run` uses the
103
111
  selected packaged application through its paired provider.
104
112
 
113
+ The package includes macOS `ArcaneCoreProcess`, `ArcaneHost` and launcher source
114
+ for explicit child launch, framed pipes, document lifecycle and graceful drain.
115
+ The SDK provider composes them with an explicitly selected Darwin Node runtime.
116
+ Source availability is not evidence of Mac compilation or execution. See the
117
+ [macOS composition boundary](reference/core-native-packaging.md#macos-application-composition).
118
+ Windows app assembly needs the normal Node/npm toolchain and `tar`, not a C#
119
+ compiler. Its generated executable uses bundled Node and requires .NET Framework
120
+ 4.6.2 or later plus WebView2 Runtime on the destination Windows x64 machine.
121
+
105
122
  Every native target accepts one selected app release and its complete bundled
106
123
  dependency closure through the provider boundary. The providers retain the
107
124
  toolchain state required for build and, where supported, launch; app source and
@@ -52,7 +52,9 @@ alone does not make bare module names resolve in a browser.
52
52
  | Call `globalThis.Arcane` | [Arcane Core API](core/arcane-api.md) |
53
53
  | Connect a browser to one Core transport | [Core browser client](core-client.md) |
54
54
  | Compose native Core dispatch, service lifecycle, and stdio hosting | [Native Core runtime](core-runtime.md) |
55
+ | Run application-selected llama.cpp, Ollama or ONNX through Core | [Local AI through Core](local-ai.md) |
55
56
  | Build an installed-SDK portable Core payload | [Portable Core packaging](core-native-packaging.md) |
57
+ | Build a Windows executable without an OS checkout | [Windows executable packaging](core-native-packaging.md#windows-executable) |
56
58
  | Subscribe to native events | [Arcane event reference](core/arcane-events.md) |
57
59
  | Use provider-neutral AI lifecycle, chat, speech, persistence, or document context | [Normalized AI](#normalized-ai) |
58
60
  | Choose a normalized typed browser decision surface | [Browser typed decisions](ai/browser-decisions.md) |
@@ -79,9 +81,11 @@ This repository contains explicitly versioned surfaces with different owners:
79
81
 
80
82
  Browser modules and reusable Core client/runtime/lifecycle source belong to the
81
83
  SDK. The portable provider uses this installed package by default and assembles
82
- an app payload with explicitly selected services; it supplies no executable
83
- platform host. Explicit Arcane OS provider overrides and integrated shared
84
- checks remain available. Arcane OS retains its product composition and policy.
84
+ an app payload with explicitly selected services; portable itself supplies no
85
+ executable host. The Windows provider pairs that payload with the installed
86
+ SDK version's precompiled WebView2/SEA release asset. Explicit Arcane OS provider
87
+ overrides and integrated shared checks remain available. Arcane OS retains its
88
+ product composition and policy.
85
89
  The historical Core reference snapshot describes a separate host contract;
86
90
  matching a protocol name or assembling a payload alone does not establish that
87
91
  a composed host supplies every required method or service.
@@ -111,6 +115,35 @@ The [changelog](../../CHANGELOG.md) records changes by version; the
111
115
  identify the corresponding published package source. A newer website does not
112
116
  change the version installed in your application.
113
117
 
118
+ ### Generate the selected reference site
119
+
120
+ The existing `node tools/build-reference-site.mjs --write` command reads the
121
+ live checkout. For release documentation while disjoint source work continues,
122
+ select the reviewed documentation commit explicitly:
123
+
124
+ ```sh
125
+ node tools/build-reference-site.mjs --write --source-ref <documentation-commit>
126
+ ```
127
+
128
+ The same option is accepted by `createReferenceSite({sourceRef})` and
129
+ `writeReferenceSite({sourceRef})`. It reads the selected commit's package
130
+ version, complete reference documents and inventories, inventory-selected
131
+ runtime sources, and authored site inputs directly from Git in memory. It
132
+ creates no checkout or export and leaves source drafts untouched. Rendering
133
+ uses the current canonical generator and its authored semantic contracts;
134
+ select a documentation commit whose contracts match the published package.
135
+ Generated output still belongs to the canonical `site/` tree and requires its
136
+ usual coordinated output ownership. Generation does not publish hosted Pages.
137
+
138
+ For a selected release whose documentation correction lands after unrelated
139
+ source, `createReferenceSite({inputs})` and `writeReferenceSite({inputs})` accept
140
+ one explicit input owner with `readText(relativePath)` and
141
+ `listFiles(relativeDirectory)`. It is shared with the contract extractor. Keep
142
+ package/runtime reads and document discovery on the release commit, and overlay
143
+ only reviewed documentation records from the correction commit. In particular,
144
+ preserve the selected inventory's member set instead of importing later public
145
+ APIs. Omitted `inputs` preserves the live or `sourceRef` behavior above.
146
+
114
147
  ### Historical 0.3.4 publication record
115
148
 
116
149
  The following records describe that earlier release only. They do not identify
@@ -181,6 +214,8 @@ Ollama, Wllama, Whisper, Kokoro, native, or cloud transport:
181
214
  | Offer explicit selected-model start/cancel UI | [`chat.html`](runtime-components.md#chathtml), [`speech.html`](runtime-components.md#speechhtml), and [`voice-transcription.html`](runtime-components.md#voice-transcriptionhtml) | Browser/native WebView components; user activation emits a cancelable request before any LLM or STT load intent, and recording stays disabled without sticky ready STT. |
182
215
  | Use Core-normalized chat | [`globalThis.Arcane.ai`](core/arcane-ai-contracts.md) | Native/Core only when separately admitted. |
183
216
  | Run a caller-selected GGUF LLM locally | [`arcane-os/ai/browser-wasm`](ai/browser-wasm.md) | Browser secure context with WebAssembly and OPFS/DBOPFS; explicit CPU selection or WebGPU with full offload and no automatic CPU fallback. |
217
+ | Run application-selected native llama.cpp/Ollama chat | [`arcane-os/ai/core-local`, `arcane-os/core/local-ai`](local-ai.md) | Explicit Core connection and selected native runtimes; installation, availability and loaded-model readiness remain distinct. |
218
+ | Run a local ONNX graph with named tensors | [`arcane-os/local-ai/onnx`, `arcane-os/ai/core-onnx`](local-ai.md#native-onnx-sessions) | Retained native workers; browser access requires an available Core ONNX service. |
184
219
  | Run caller-selected Whisper/Kokoro locally | [`arcane-os/ai/browser-speech`](ai/browser-speech.md) | Browser with DBOPFS, Web Locks, Workers and selected upstream sources; automatic WebNN NPU, WebGPU, then WASM loading, or an explicit backend. |
185
220
  | Use native browser recognition/voices or selected cloud TTS | [Speech provider choices](ai/browser-speech.md) | Native APIs depend on the browser and may use remote services; cloud TTS requires the application key and endpoint access. |
186
221
  | Send complete chat, System One or image requests without retained history | [`arcane-os/ai/twin-cloud`](ai/twin-cloud.md) | Node or browser with Fetch and explicit model/credentials; image results contain every returned image as a Blob. |
@@ -58,12 +58,12 @@ false when a probe throws; SDK branching continues through its owning error path
58
58
  policy, package-owned model policy, platform support, and dependency readiness
59
59
  are independent checks.
60
60
 
61
- The current executable host/target matrix covers Microsoft NT, Linux, and
62
- Android where listed. This SDK exposes no macOS executable target, native
63
- bridge, artifact, or run contract; WebKitGTK availability must not be
64
- generalized to macOS. The reusable Node Core runtime, framed stdio transport,
65
- host composition, and portable payload can be used by a separately composed
66
- macOS host, but they do not supply that native platform host or bridge.
61
+ Windows x64 has an SDK-owned precompiled WebView2/SEA host; Linux and Android
62
+ retain their explicit checkout providers where listed. The SDK also includes
63
+ macOS Foundation process-adapter source, separately from an executable target,
64
+ renderer bridge, artifact or run command. A composed macOS host may combine that
65
+ source with the reusable Node Core runtime, stdio transport and portable payload.
66
+ Source availability does not establish macOS compilation or execution.
67
67
 
68
68
  ## Capability-first matrix
69
69
 
@@ -89,6 +89,9 @@ macOS host, but they do not supply that native platform host or bridge.
89
89
  | Connect browser code to an existing Core transport | `arcane-os/core/client` and `arcane-os/core/contracts` | **Browser / native WebView** with an admitted transport; explicit development HTTP remains opt-in | The reusable client owns `arcane/1` correlation, readiness, cancellation, events, facades, and complete native error fidelity. It supplies no service, policy, or host process. |
90
90
  | Compose native Core services and framed stdio hosting | `arcane-os/core/runtime`, `arcane-os/core/stdio`, and `arcane-os/core/host` | **Node** on Windows, Linux, or macOS; the composing native host supplies its process and bridge | The SDK owns reusable dispatch, per-service lifecycle, request/service work ownership, cooperative cancellation, drain, and stdio framing. Product identity, policy, privileges, models, storage, and services remain host-owned. |
91
91
  | Assemble a portable Core payload from the installed SDK | `arcane-os/native/portable-provider` | **Node**; portable platform selection is currently Windows or Linux, while separately composed hosts may use the payload | The provider copies the selected app, dependencies, installed SDK runtime, Core client/runtime, and explicit service composition into a non-executable directory. It uses no `arcaneRoot` by default and does not prove host behavior or supply a platform bridge. |
92
+ | Assemble and run a Windows executable | [`arcane-os/native/windows-provider`](core-native-packaging.md#windows-executable) | **Node** for assembly; Windows x64, .NET Framework 4.6.2+ and WebView2 for execution | Uses the installed SDK version's precompiled release asset and explicit app services. Complete diagnostics and accepted service work drain on run cancellation; no OS checkout or application-side native compiler is required. |
93
+ | Use application-selected llama.cpp/Ollama through Core | [`arcane-os/core/local-ai`, `arcane-os/ai/core-local`](local-ai.md) | **Node** native service; **Browser / native WebView** provider through an explicit Core connection | Independent runtime/model lifecycle, complete streaming and cancellation. Official runtime preparation follows explicit app requirements; model selection and business policy stay app-owned. |
94
+ | Run native ONNX tensors | [`arcane-os/local-ai/onnx`, `arcane-os/ai/core-onnx`](local-ai.md#native-onnx-sessions) | **Node** Windows/Linux/macOS x64/arm64; **Browser / native WebView** through available Core | Explicit graph loading, retained workers and complete tensor outputs. Android requires host adaptation. Native calls can delay worker termination; cleanup observes actual exit. |
92
95
  | Use local AI without coupling app code to Ollama HTTP | `Arcane.localAI`, `Arcane.ai`, or `/arcane/modules/Ollama.js` | Primarily **Native**; Android exposes a narrower admitted inference projection | Admission, errors, and managed-operation events are normalized. Direct Ollama response envelopes remain **Provider-native**. |
93
96
  | Use TWiN Cloud from the renderer profile | `/arcane/modules/AI.js` | **Cloud** from an allowed browser/native renderer | High-level chat behavior is normalized by the module. The TWiN access key authenticates remote LLM chat; raw provider diagnostics remain provider-specific. No automatic cloud fallback is inferred from local failure. |
94
97
  | Send one TWiN Cloud request with an explicit key and model | `fetchRequest` from `arcane-os/ai/twin-cloud` | **Node** and **Browser**, using standard Fetch and a remote HTTPS provider | Keeps complete messages and returns the full parsed provider JSON. Rejected Fetch and HTTP 529 share three retries after 3000 ms; HTTP 429 overload retains unlimited three-second retries. Optional `onRetry` reports waiting/requesting phases without blocking recovery. Shared structured-output mapping and cancellation match browser TWiN transport. No browser profile, AI/user singleton, DBOPFS, or retained request history is created. |
@@ -49,6 +49,7 @@ meaning and cardinality rules:
49
49
  | `--app` | app id or label | Workspace/app operations except shared scope and `verify-bundle`; optional diagnostic label for `mail serve`. |
50
50
  | `--apps-root` | `.` or `apps` | `new`, `init`; standalone setup defaults to the repository root. |
51
51
  | `--sdk-runtime-source` | SDK checkout directory | `dev` only; maps live SDK source through the selected browser destinations for that server process. |
52
+ | `--local-ai` | comma-separated runtime IDs | `dev` only; adds `llama.cpp`, `ollama` and/or `onnx` requirements to application configuration and prepares missing runtimes alongside serving. See [local AI through Core](local-ai.md). |
52
53
  | `--arcane-root` | directory | `doctor`, native `build`/`run`, `native-doctor`, `native-prepare` |
53
54
  | `--host` / `--port` | host / integer 0–65535 | Browser `dev`/`run` default to HTTPS at `127.0.0.1:8000`; `mail serve` defaults to HTTPS with HTTP/2 at `0.0.0.0:4433` and accepts an explicit bind host. |
54
55
  | `--http-port` | integer 0–65535 | Browser `dev`/`run` HTTP redirect listener; defaults to `0`, which selects an available port. |
@@ -366,9 +367,16 @@ An explicit live-source SDK mapping follows the selected browser destinations
366
367
  while reading canonical SDK source; it never replaces installed files.
367
368
 
368
369
  ```text
369
- arcane dev [--app <id>] [--public] [--http | --https] [--cert <file> --key <file>] [--host <address>] [--port 8000] [--http-port 0] [--sdk-runtime-source <sdk-root>]
370
+ arcane dev [--app <id>] [--public] [--http | --https] [--cert <file> --key <file>] [--host <address>] [--port 8000] [--http-port 0] [--sdk-runtime-source <sdk-root>] [--local-ai llama.cpp,ollama,onnx]
370
371
  ```
371
372
 
373
+ `--local-ai` saves the selected requirements in `native.localAI`, or in
374
+ `arcane-package.json.localAI` for a package-only app. Later development runs
375
+ reuse them. Available services and executables are reused; missing runtimes
376
+ are installed inside the application while serving starts independently.
377
+ Applications choose their model files and optional browser Core connection.
378
+ See [local AI through Core](local-ai.md) for configuration and native bundling.
379
+
372
380
  ### Lifecycle
373
381
 
374
382
  Startup refreshes the selected authored `arcane-app.json` projection into
@@ -398,7 +406,7 @@ device, since `localhost` refers to that device and `0.0.0.0` is a bind address.
398
406
  Network URLs come from one interface snapshot at startup and do not establish
399
407
  remote reachability through the machine's firewall or network.
400
408
 
401
- HTTPS is the default for development and required for packaged browser previews.
409
+ HTTPS is the default for development and packaged browser previews.
402
410
  The published `node-http-server` 10.0.0 integration negotiates HTTP/2 or HTTP/1.1
403
411
  on the same HTTPS port using the configured PEM pair. Source routes, generated
404
412
  PWA resources, and conditional responses use the same serving pipeline.
@@ -440,6 +448,10 @@ close the owned HTTP listener and settle the same lifecycle.
440
448
  `--key`, or `--http-port` is a usage error. Omitting it preserves HTTPS;
441
449
  certificate errors never select HTTP automatically.
442
450
 
451
+ The public `startDevServer()` API also accepts `http:true` in packaged mode;
452
+ this does not add a CLI preview command or change `dev` into packaged serving.
453
+ See [the API contract](sdk-api.md#startdevserver).
454
+
443
455
  A LAN HTTP origin does not receive the browser's localhost secure-context
444
456
  exception. For Chrome development, Chromium documents
445
457
  `chrome://flags/#unsafely-treat-insecure-origin-as-secure` with the exact HTTP
@@ -692,10 +704,10 @@ npm exec -- arcane verify-bundle dist/hello-world-1.0.0.arcane-app.tar.gz
692
704
 
693
705
  ### Overview
694
706
 
695
- Loads the SDK package provider for portable by default, or the fixed provider
696
- from an explicitly selected Arcane OS checkout. It diagnoses the selected
697
- provider prerequisites without building an app. Executable targets still
698
- require `--arcane-root` and their platform toolchains.
707
+ Loads the SDK package provider for `portable` or `windows-x64` by default, or
708
+ the fixed provider from an explicitly selected Arcane OS checkout. It diagnoses
709
+ selected prerequisites without building an app. Windows uses the matching
710
+ precompiled SDK host; Linux and Android retain their checkout/toolchain routes.
699
711
 
700
712
  ```text
701
713
  arcane native-doctor --target <native-target> [--arcane-root <directory>]
@@ -711,8 +723,7 @@ is unavailable; it never returns a browser package as a substitute.
711
723
 
712
724
  ```bash
713
725
  npm exec -- arcane native-doctor \
714
- --target windows-x64 \
715
- --arcane-root "../Arcane OS"
726
+ --target windows-x64
716
727
  ```
717
728
 
718
729
  ## `arcane native-prepare`
@@ -754,6 +765,9 @@ The output remains target-specific inside the common plan contract.
754
765
  Portable uses the SDK package without an OS checkout, copies complete selected
755
766
  app/dependency payloads and generates the Core entry/classic client source.
756
767
  It adds no executable platform host or automatically discovered app services.
768
+ Windows x64 uses the SDK package provider and its matching precompiled release
769
+ asset without an OS checkout or application-side native compilation. See
770
+ [Windows requirements and artifact layout](core-native-packaging.md#windows-executable).
757
771
  An explicit `--arcane-root` continues to select the checkout provider.
758
772
  Integrated builds retain an output root outside the OS checkout; only an
759
773
  explicit checkout provider must share the workspace root.
@@ -767,7 +781,6 @@ rather than returning a fictional native artifact plan.
767
781
  ```bash
768
782
  npm exec -- arcane build \
769
783
  --target windows-x64 \
770
- --arcane-root "../Arcane OS" \
771
784
  --output-root "../arcane-native-output"
772
785
  ```
773
786
 
@@ -808,6 +821,13 @@ Android providers expose supported paired native run paths. Portable output is
808
821
  a directory and intentionally cannot run. Android run requires one
809
822
  connected physical/native ARM64 device for the current target.
810
823
 
824
+ `windows-x64` uses the package provider by default, launches `Arcane.exe`, and
825
+ streams complete diagnostics. Its cancellation closes input and waits for the
826
+ window/Core's accepted work to drain; it does not force-kill that host after a
827
+ timer. WebView2 Runtime and .NET Framework 4.6.2 or later must be available on
828
+ the Windows execution machine. Linux/Android retain their explicit provider
829
+ requirements. Build/launch completion does not prove application domain behavior.
830
+
811
831
  ### Example
812
832
 
813
833
  ```bash