arcane-os 0.3.0 → 0.3.2

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 (153) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +86 -117
  3. package/bin/arcane-test.mjs +170 -46
  4. package/browser-runtime/ai/browser-speech-artifacts.mjs +887 -909
  5. package/browser-runtime/ai/browser-speech-providers.mjs +96 -152
  6. package/browser-runtime/ai/browser-wasm-llm-provider.mjs +627 -819
  7. package/browser-runtime/ai/browser-wasm.mjs +24 -35
  8. package/browser-runtime/ai/browser-wllama-runtime.mjs +64 -316
  9. package/browser-runtime/ai/model-controller.mjs +584 -181
  10. package/browser-runtime/ai/speech-worker-client.mjs +8 -146
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +643 -363
  12. package/browser-runtime/dom-event-instrumentation.mjs +55 -147
  13. package/browser-runtime/event-manager.mjs +239 -624
  14. package/package.json +5 -6
  15. package/runtime/arcane/components/app-bar.html +3 -15
  16. package/runtime/arcane/components/assistant-panel.html +10 -10
  17. package/runtime/arcane/components/calculator.html +1 -1
  18. package/runtime/arcane/components/chat.html +1359 -135
  19. package/runtime/arcane/components/conversation-view.html +2 -2
  20. package/runtime/arcane/components/document-inspector.html +11 -17
  21. package/runtime/arcane/components/file-manager.html +13 -56
  22. package/runtime/arcane/components/markdown-document.html +82 -281
  23. package/runtime/arcane/components/markdown-editor.html +7 -10
  24. package/runtime/arcane/components/media-embed.html +6 -6
  25. package/runtime/arcane/components/screen-capture.html +4 -4
  26. package/runtime/arcane/components/source-explanation.html +2 -2
  27. package/runtime/arcane/components/speech.html +112 -68
  28. package/runtime/arcane/components/terminal-workspace.html +4 -4
  29. package/runtime/arcane/components/theme-editor.html +1 -1
  30. package/runtime/arcane/components/unified-inbox.html +2 -2
  31. package/runtime/arcane/components/voice-transcription.html +31 -21
  32. package/runtime/arcane/entities/Calculation.js +2 -3
  33. package/runtime/arcane/entities/Chat.js +228 -43
  34. package/runtime/arcane/entities/Preference.js +3 -5
  35. package/runtime/arcane/entities/Weather.js +5 -5
  36. package/runtime/arcane/modules/AI.js +1050 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +658 -363
  38. package/runtime/arcane/modules/AIResponseLength.js +9 -19
  39. package/runtime/arcane/modules/AIRuntimeState.js +109 -72
  40. package/runtime/arcane/modules/ArcaneNavigationPolicy.js +45 -32
  41. package/runtime/arcane/modules/BrowserTestSuite.js +78 -122
  42. package/runtime/arcane/modules/CalculatorEngine.js +9 -9
  43. package/runtime/arcane/modules/CommunicationAppController.js +3 -7
  44. package/runtime/arcane/modules/ComponentContracts.js +30 -32
  45. package/runtime/arcane/modules/ConfiguredAIChatSession.js +281 -230
  46. package/runtime/arcane/modules/ConversationActionItems.js +26 -59
  47. package/runtime/arcane/modules/ConversationClosingReport.js +34 -61
  48. package/runtime/arcane/modules/ConversationTimebox.js +27 -15
  49. package/runtime/arcane/modules/DBOPFSDocumentLibrary.js +152 -344
  50. package/runtime/arcane/modules/DocumentLexicalSearch.js +25 -91
  51. package/runtime/arcane/modules/HTMLImport.js +54 -1
  52. package/runtime/arcane/modules/IsolatedModelQuestionRunner.js +40 -203
  53. package/runtime/arcane/modules/LocalAIReadiness.js +40 -60
  54. package/runtime/arcane/modules/LocalAIReadinessController.js +15 -13
  55. package/runtime/arcane/modules/MD.js +1 -45
  56. package/runtime/arcane/modules/Mail.js +51 -103
  57. package/runtime/arcane/modules/MailOutbox.mjs +95 -193
  58. package/runtime/arcane/modules/MailTransport.mjs +36 -57
  59. package/runtime/arcane/modules/ModelDefinition.js +22 -106
  60. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +39 -101
  61. package/runtime/arcane/modules/PersistentAIChatSession.js +281 -18
  62. package/runtime/arcane/modules/PreferenceStore.js +102 -30
  63. package/runtime/arcane/modules/RiskSignalAnalyzer.js +8 -9
  64. package/runtime/arcane/modules/ScopedOPFSCache.js +7 -42
  65. package/runtime/arcane/modules/ScreenCapture.js +175 -128
  66. package/runtime/arcane/modules/SpeechPlayback.js +46 -149
  67. package/runtime/arcane/modules/StaticDocumentCatalog.js +173 -407
  68. package/runtime/arcane/modules/ToolCallRouter.js +25 -12
  69. package/runtime/arcane/modules/YouTubeMedia.js +6 -5
  70. package/schemas/arcane-app-bundle.schema.json +13 -78
  71. package/schemas/arcane-app.schema.json +9 -25
  72. package/schemas/arcane-lock.schema.json +18 -151
  73. package/schemas/arcane-package.schema.json +2 -16
  74. package/schemas/native-build-plan.schema.json +119 -122
  75. package/src/app-descriptor.mjs +75 -132
  76. package/src/application-tests.mjs +200 -0
  77. package/src/cli/main.mjs +27 -46
  78. package/src/constants.mjs +3 -4
  79. package/src/dev-server.mjs +30 -324
  80. package/src/doctor.mjs +92 -154
  81. package/src/dom-event-instrumentation.mjs +55 -147
  82. package/src/errors.mjs +2 -3
  83. package/src/event-manager.mjs +239 -624
  84. package/src/event-queue.mjs +3 -3
  85. package/src/import-map.mjs +273 -1028
  86. package/src/index.mjs +14 -16
  87. package/src/installed-sdk-runtime.mjs +40 -62
  88. package/src/integrated-provider-loader.mjs +53 -382
  89. package/src/mail-api.mjs +0 -2
  90. package/src/mail-server.mjs +224 -580
  91. package/src/mail.mjs +4 -10
  92. package/src/native-plan.mjs +163 -598
  93. package/src/native-provider-loader.mjs +104 -1063
  94. package/src/packager/core.mjs +485 -3229
  95. package/src/process.mjs +5 -10
  96. package/src/release-bundle.mjs +292 -2405
  97. package/src/runtime.mjs +76 -396
  98. package/src/scaffold.mjs +30 -80
  99. package/src/sdk-browser-runtime.mjs +70 -626
  100. package/src/source-server.mjs +588 -0
  101. package/src/targets/index.mjs +78 -188
  102. package/src/templates/workspace-template.mjs +19 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +131 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +112 -779
  109. package/src/workspace.mjs +40 -302
  110. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +0 -218
  111. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +0 -203
  112. package/browser-runtime/ai/ARCANE_AI_BROWSER_WASM_COMPONENTS.json +0 -80
  113. package/browser-runtime/ai/internal/sha256.mjs +0 -166
  114. package/docs/architecture.md +0 -344
  115. package/docs/compatibility.md +0 -36
  116. package/docs/event-manager.md +0 -294
  117. package/docs/platform-targets.md +0 -108
  118. package/docs/publishing.md +0 -201
  119. package/docs/reference/README.md +0 -187
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1252
  122. package/docs/reference/ai/browser-wasm.md +0 -530
  123. package/docs/reference/arcane-ollama.md +0 -288
  124. package/docs/reference/availability-and-normalization.md +0 -183
  125. package/docs/reference/behavioral-testing.md +0 -133
  126. package/docs/reference/cli.md +0 -779
  127. package/docs/reference/core/README.md +0 -62
  128. package/docs/reference/core/arcane-ai-contracts.md +0 -907
  129. package/docs/reference/core/arcane-api.md +0 -601
  130. package/docs/reference/core/arcane-entities.md +0 -65
  131. package/docs/reference/core/arcane-events.md +0 -134
  132. package/docs/reference/core/ollama-module.md +0 -181
  133. package/docs/reference/core/reference/arcane-api/ai-and-ollama.md +0 -1909
  134. package/docs/reference/core/reference/arcane-api/applications-terminal-capabilities.md +0 -1057
  135. package/docs/reference/core/reference/arcane-api/core-and-events.md +0 -320
  136. package/docs/reference/core/reference/arcane-api/filesystem-storage-preferences-appearance.md +0 -610
  137. package/docs/reference/core/reference/arcane-api/namespaces.md +0 -1157
  138. package/docs/reference/core/reference/arcane-api/platform-installation-users-system.md +0 -1423
  139. package/docs/reference/core/reference/arcane-api/session-provisioning-diagnostics-development.md +0 -315
  140. package/docs/reference/event-manager.md +0 -1511
  141. package/docs/reference/inventory/package-api.json +0 -3284
  142. package/docs/reference/inventory/runtime-components.json +0 -1011
  143. package/docs/reference/inventory/runtime-entities.json +0 -26
  144. package/docs/reference/inventory/runtime-modules.json +0 -1431
  145. package/docs/reference/mail.md +0 -316
  146. package/docs/reference/protocols.md +0 -677
  147. package/docs/reference/runtime-components.md +0 -1366
  148. package/docs/reference/runtime-entities.md +0 -303
  149. package/docs/reference/runtime-modules.md +0 -2960
  150. package/docs/reference/sdk-api.md +0 -6694
  151. package/docs/roadmap.md +0 -79
  152. package/docs/work-amplification.md +0 -129
  153. package/runtime/ARCANE_RUNTIME_RELEASE.json +0 -826
package/src/toolchain.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import path from 'node:path';
2
2
  import {readdir,lstat,realpath} from 'node:fs/promises';
3
- import {fileURLToPath} from 'node:url';
4
3
  import {createWorkspace,initWorkspace} from './scaffold.mjs';
5
4
  import {
6
5
  discoverApps as discoverWorkspaceApps,
@@ -11,26 +10,16 @@ import {
11
10
  } from './workspace.mjs';
12
11
  import {loadArcaneIntegratedProvider} from './integrated-provider-loader.mjs';
13
12
  import {startDevServer} from './dev-server.mjs';
14
- import {authenticateRuntimeReceipt,verifyRuntime} from './runtime.mjs';
15
- import {
16
- authenticateSdkBrowserRuntimeReceipt,
17
- verifySdkBrowserRuntime
18
- } from './sdk-browser-runtime.mjs';
19
- import {
20
- authenticateWorkspaceRuntimeReceipt,
21
- verifyWorkspaceRuntime
22
- } from './workspace-runtime.mjs';
23
13
  import {generateImportMap} from './import-map.mjs';
24
14
  import {withWorkspaceOperationLock} from './workspace-operation-lock.mjs';
25
15
  import {
26
- authenticateSharedPayloadSnapshot,
16
+ inspectApp as inspectPackagedApp,
27
17
  packageApp,
28
- prepareSharedPayloadSnapshot,
29
18
  verifyApp
30
19
  } from './packager/core.mjs';
31
- import {assertNativeToolchainCompatibility} from './native-plan.mjs';
32
20
  import {runDoctor} from './doctor.mjs';
33
21
  import {runProcess} from './process.mjs';
22
+ import {runApplicationTests} from './application-tests.mjs';
34
23
  import {
35
24
  buildTarget,
36
25
  createNativeTargetAdapter,
@@ -50,132 +39,34 @@ import {
50
39
  verifyAppReleaseBundle
51
40
  } from './release-bundle.mjs';
52
41
 
53
- const TEST_RUNNER_PATH=fileURLToPath(new URL('../bin/arcane-test.mjs',import.meta.url));
54
- const MAX_TEST_FAILURE_STREAM_BYTES=32*1024;
55
- const MAX_TEST_FAILURE_AGGREGATE_BYTES=256*1024;
56
- const MAX_TEST_FAILURE_MESSAGE_BYTES=24*1024;
57
- const TEST_OUTPUT_TRUNCATION_NOTICE='[... earlier test output omitted ...]\n';
58
-
59
- function normalizedTestOutput(value){
60
- return typeof value==='string'?value.trim():'';
61
- }
62
-
63
- function boundedTestOutputTail(value,maxBytes){
64
- const source=normalizedTestOutput(value);
65
- const sourceBytes=Buffer.byteLength(source,'utf8');
66
- if(sourceBytes<=maxBytes){
67
- return {text:source,bytes:sourceBytes,truncated:false};
68
- }
69
- const noticeBytes=Buffer.byteLength(TEST_OUTPUT_TRUNCATION_NOTICE,'utf8');
70
- if(maxBytes<noticeBytes){
71
- return {text:'',bytes:0,truncated:sourceBytes>0};
72
- }
73
- const buffer=Buffer.from(source,'utf8');
74
- let start=buffer.length-(maxBytes-noticeBytes);
75
- while(start<buffer.length&&(buffer[start]&0xc0)===0x80){
76
- start+=1;
77
- }
78
- const text=`${TEST_OUTPUT_TRUNCATION_NOTICE}${buffer.subarray(start).toString('utf8')}`;
79
- return {text,bytes:Buffer.byteLength(text,'utf8'),truncated:true};
80
- }
81
-
82
- function failedTestOutputBudgets(stderr,stdout,maxBytes){
83
- const desiredStderr=Math.min(
84
- MAX_TEST_FAILURE_STREAM_BYTES,
85
- Buffer.byteLength(normalizedTestOutput(stderr),'utf8')
86
- );
87
- const desiredStdout=Math.min(
88
- MAX_TEST_FAILURE_STREAM_BYTES,
89
- Buffer.byteLength(normalizedTestOutput(stdout),'utf8')
90
- );
91
- if(desiredStderr+desiredStdout<=maxBytes){
92
- return {stderr:desiredStderr,stdout:desiredStdout};
93
- }
94
- const shared=Math.floor(maxBytes/2);
95
- let stderrBudget=Math.min(desiredStderr,shared);
96
- let stdoutBudget=Math.min(desiredStdout,shared);
97
- let remaining=maxBytes-stderrBudget-stdoutBudget;
98
- const additionalStderr=Math.min(remaining,desiredStderr-stderrBudget);
99
- stderrBudget+=additionalStderr;
100
- remaining-=additionalStderr;
101
- stdoutBudget+=Math.min(remaining,desiredStdout-stdoutBudget);
102
- return {stderr:stderrBudget,stdout:stdoutBudget};
103
- }
104
-
105
- function captureFailedTest(testFile,result,workspaceRoot,maxBytes){
106
- const budgets=failedTestOutputBudgets(result.stderr,result.stdout,maxBytes);
107
- const stderr=boundedTestOutputTail(result.stderr,budgets.stderr);
108
- const stdout=boundedTestOutputTail(result.stdout,budgets.stdout);
109
- return {
110
- failure:Object.freeze({
111
- testFile:path.relative(workspaceRoot,testFile).replaceAll('\\','/'),
112
- exitCode:result.code,
113
- signal:result.signal,
114
- stdout:stdout.text,
115
- stderr:stderr.text,
116
- stdoutTruncated:stdout.truncated,
117
- stderrTruncated:stderr.truncated
118
- }),
119
- bytes:stdout.bytes+stderr.bytes
120
- };
121
- }
122
-
123
- function failedTestMessage(failures){
124
- const summary=`${String(failures.length)} isolated test file${failures.length===1?'':'s'} failed.`;
125
- const actionable=failures.find(failure=>failure.stderr||failure.stdout);
126
- if(!actionable){
127
- return summary;
128
- }
129
- const heading=`\n\n${actionable.testFile}:\n`;
130
- const available=Math.max(
131
- 0,
132
- MAX_TEST_FAILURE_MESSAGE_BYTES-Buffer.byteLength(`${summary}${heading}`,'utf8')
133
- );
134
- const diagnostic=boundedTestOutputTail(
135
- actionable.stderr||actionable.stdout,
136
- available
137
- ).text;
138
- return diagnostic?`${summary}${heading}${diagnostic}`:summary;
139
- }
140
-
141
42
  async function emit(onEvent,event){
142
43
  await onEvent?.(event);
143
44
  }
144
45
 
145
- function nativeArtifactReceipt(result){
146
- return result?.artifactReceipt??result?.built?.artifactReceipt??null;
147
- }
148
-
149
46
  function withEventDeliveryFailure(result,error){
150
- const eventDelivery=Object.freeze({
47
+ const eventDelivery={
151
48
  status:'degraded',
152
49
  errorCode:'ARCANE_EVENT_DELIVERY_FAILED',
153
50
  message:String(error?.message??error)
154
- });
155
- if(result?.built?.artifactReceipt){
51
+ };
52
+ if(result?.built?.artifact){
156
53
  return {...result,built:{...result.built,eventDelivery}};
157
54
  }
158
55
  return {...result,eventDelivery};
159
56
  }
160
57
 
161
58
  function isOuterCommitEvent(label,event){
162
- if(label==='build')return event?.type==='native.build.committed';
163
- return label==='bundle'&&event?.type==='bundle.committed'
59
+ if(label==='build')return event?.type==='native.build.completed';
60
+ return label==='bundle'&&event?.type==='bundle.completed'
164
61
  &&event?.phase==='publish'&&event?.status==='completed';
165
62
  }
166
63
 
167
- function isAppReleaseReceipt(value){
168
- return value?.kind==='arcane-app-release-verification'
169
- &&typeof value?.contentSha256==='string';
170
- }
171
-
172
- function hasAuthenticatedOuterResult(label,result){
64
+ function hasCommittedOuterResult(label,result){
173
65
  if(label==='import-map')return result?.committed===true;
174
- if(label==='package')return isAppReleaseReceipt(result?.receipt);
175
- if(label==='bundle')return result?.artifactReceipt?.kind
176
- ==='arcane-app-release-bundle-artifact';
66
+ if(label==='package')return typeof result?.outputRoot==='string';
67
+ if(label==='bundle')return typeof result?.bundlePath==='string';
177
68
  if(label!=='build')return false;
178
- return nativeArtifactReceipt(result)!=null||isAppReleaseReceipt(result?.release?.receipt);
69
+ return result?.artifact!=null||typeof result?.release?.outputRoot==='string';
179
70
  }
180
71
 
181
72
  async function ownedWork(label,work,{
@@ -247,7 +138,7 @@ async function ownedWork(label,work,{
247
138
  onEvent:forwardEvent
248
139
  },execute)
249
140
  :await execute();
250
- if(hasAuthenticatedOuterResult(label,result))committed=true;
141
+ if(hasCommittedOuterResult(label,result))committed=true;
251
142
  stopProducers();
252
143
  if(!committed||label==='run')throwIfAborted(controller.signal);
253
144
  try{
@@ -276,33 +167,6 @@ async function ownedWork(label,work,{
276
167
  }
277
168
  }
278
169
 
279
- async function collectTests(root,files,signal){
280
- let entries;
281
- try{
282
- entries=await readdir(root,{withFileTypes:true});
283
- }catch(error){
284
- if(error?.code==='ENOENT'){
285
- return;
286
- }
287
- throw error;
288
- }
289
- for(const entry of entries.sort((left,right)=>left.name.localeCompare(right.name,'en'))){
290
- throwIfAborted(signal);
291
- const absolute=path.join(root,entry.name);
292
- if(entry.isSymbolicLink()){
293
- continue;
294
- }
295
- if(entry.isDirectory()){
296
- await collectTests(absolute,files,signal);
297
- }else if(entry.isFile()&&/\.test\.(?:mjs|cjs|js)$/u.test(entry.name)){
298
- const info=await lstat(absolute);
299
- if(info.isFile()&&!info.isSymbolicLink()){
300
- files.add(absolute);
301
- }
302
- }
303
- }
304
- }
305
-
306
170
  async function selectedWorkspace(options){
307
171
  const resolved=await resolveWorkspace({
308
172
  workspaceRoot:options.workspaceRoot,
@@ -360,13 +224,12 @@ async function executeIntegratedSharedOperation(operation,options){
360
224
  signal,
361
225
  onEvent
362
226
  });
363
- return Object.freeze({
227
+ return {
364
228
  scope:'shared',
365
229
  workspaceMode:'integrated',
366
230
  workspaceRoot:profile.workspaceRoot,
367
- providerGeneration:provider.providerGeneration,
368
231
  result
369
- });
232
+ };
370
233
  },
371
234
  options
372
235
  );
@@ -386,7 +249,7 @@ async function preparedWorkspace(options){
386
249
  ||typeof workspace.sdkInstallation.browserRuntimeRoot!=='string')){
387
250
  throw new ArcaneError(
388
251
  ERROR_CODES.workspaceInvalid,
389
- 'Validated external workspace is missing its bound SDK installation authority.'
252
+ 'Validated external workspace is missing its SDK runtime directories.'
390
253
  );
391
254
  }
392
255
  const runtimeRoot=external
@@ -395,39 +258,7 @@ async function preparedWorkspace(options){
395
258
  const browserRuntimeRoot=external
396
259
  ?workspace.sdkInstallation.browserRuntimeRoot
397
260
  :null;
398
- const runtimeReceipt=external&&!options.deferRuntimeVerification
399
- ?await verifyRuntime({
400
- runtimeRoot,
401
- signal:options.signal,
402
- onEvent:options.onEvent
403
- })
404
- :null;
405
- const sdkBrowserRuntimeReceipt=external&&!options.deferRuntimeVerification
406
- ?await verifySdkBrowserRuntime({
407
- browserRuntimeRoot,
408
- signal:options.signal,
409
- onEvent:options.onEvent
410
- })
411
- :null;
412
- const workspaceRuntimeReceipt=external&&!options.deferRuntimeVerification
413
- ?await verifyWorkspaceRuntime({
414
- workspaceRoot:workspace.workspaceRoot,
415
- runtimeRoot,
416
- runtimeReceipt,
417
- browserRuntimeRoot,
418
- sdkBrowserRuntimeReceipt,
419
- signal:options.signal,
420
- onEvent:options.onEvent
421
- })
422
- :null;
423
- const runtimeVerificationState=external&&!options.deferRuntimeVerification
424
- ?Object.freeze({runtimeReceipt,sdkBrowserRuntimeReceipt,workspaceRuntimeReceipt})
425
- :null;
426
261
  return {
427
- runtimeReceipt,
428
- sdkBrowserRuntimeReceipt,
429
- workspaceRuntimeReceipt,
430
- runtimeVerificationState,
431
262
  runtimeRoot,
432
263
  browserRuntimeRoot,
433
264
  workspaceMode:workspace.workspaceMode,
@@ -440,146 +271,14 @@ async function preparedWorkspace(options){
440
271
  };
441
272
  }
442
273
 
443
- function forwardedRuntimeVerificationState(options,prepared){
444
- return Object.hasOwn(options,'runtimeVerificationState')
445
- ?options.runtimeVerificationState
446
- :prepared.runtimeVerificationState??undefined;
447
- }
448
-
449
- function compareRuntimeInventory(left,right){
450
- return left.path.localeCompare(right.path,'en');
451
- }
452
-
453
- async function externalRuntimeSnapshotReceipt(prepared,sharedPayloadSnapshot,sharedPayloadIds,{signal,onEvent}={}){
454
- throwIfAborted(signal);
455
- await authenticateSharedPayloadSnapshot(sharedPayloadSnapshot,{
456
- workspaceRoot:prepared.workspaceRoot,
457
- sharedPayloadIds,
458
- signal
459
- });
460
- const runtimeReceipt=await verifyRuntime({
461
- runtimeRoot:prepared.runtimeRoot,
462
- signal,
463
- onEvent
464
- });
465
- const sdkBrowserRuntimeReceipt=await verifySdkBrowserRuntime({
466
- browserRuntimeRoot:prepared.browserRuntimeRoot,
467
- signal,
468
- onEvent
469
- });
470
- const workspaceRuntimeReceipt=await verifyWorkspaceRuntime({
471
- workspaceRoot:prepared.workspaceRoot,
472
- runtimeRoot:prepared.runtimeRoot,
473
- runtimeReceipt,
474
- browserRuntimeRoot:prepared.browserRuntimeRoot,
475
- sdkBrowserRuntimeReceipt,
476
- signal,
477
- onEvent
478
- });
479
- const retained=sharedPayloadSnapshot.files
480
- .filter(file=>file.source.startsWith('arcane/'))
481
- .map(file=>Object.freeze({
482
- path:file.source.slice('arcane/'.length),
483
- bytes:file.bytes,
484
- sha256:file.sha256
485
- }))
486
- .sort(compareRuntimeInventory);
487
- const upstreamFiles=runtimeReceipt.files.map(file=>Object.freeze({
488
- path:file.path.startsWith('arcane/')
489
- ?file.path.slice('arcane/'.length)
490
- :`dependencies/strong-type/${file.path.slice('strong-type/'.length)}`,
491
- sourcePath:file.path,
492
- bytes:file.bytes,
493
- sha256:file.sha256
494
- })).sort(compareRuntimeInventory);
495
- const sdkFiles=sdkBrowserRuntimeReceipt.files.map(file=>Object.freeze({
496
- path:`sdk/${file.path}`,
497
- sourcePath:file.path,
498
- bytes:file.bytes,
499
- sha256:file.sha256
500
- })).sort(compareRuntimeInventory);
501
- const expected=[...upstreamFiles,...sdkFiles]
502
- .map(file=>Object.freeze({path:file.path,bytes:file.bytes,sha256:file.sha256}))
503
- .sort(compareRuntimeInventory);
504
- if(JSON.stringify(retained)!==JSON.stringify(expected)){
505
- throw new ArcaneError(
506
- ERROR_CODES.integrityFailed,
507
- 'The retained shared payload does not match the composed Arcane and SDK browser runtime receipts.'
508
- );
509
- }
510
- const receipt=Object.freeze({
511
- schemaVersion:1,
512
- kind:'arcane-sdk-runtime-shared-payload',
513
- canonicalLocation:prepared.runtimeRoot,
514
- source:Object.freeze({...runtimeReceipt.source}),
515
- sources:Object.freeze({
516
- arcane:Object.freeze({
517
- manifestSha256:runtimeReceipt.manifestSha256,
518
- contentSha256:runtimeReceipt.contentSha256,
519
- source:runtimeReceipt.source
520
- }),
521
- sdkBrowser:Object.freeze({
522
- manifestSha256:sdkBrowserRuntimeReceipt.manifestSha256,
523
- contentSha256:sdkBrowserRuntimeReceipt.contentSha256,
524
- source:sdkBrowserRuntimeReceipt.source
525
- })
526
- }),
527
- files:Object.freeze(runtimeReceipt.files.map(file=>Object.freeze({...file}))),
528
- fileCount:runtimeReceipt.fileCount,
529
- totalBytes:runtimeReceipt.totalBytes,
530
- contentSha256:runtimeReceipt.contentSha256,
531
- browserFiles:Object.freeze(sdkBrowserRuntimeReceipt.files.map(
532
- file=>Object.freeze({...file})
533
- )),
534
- browserFileCount:sdkBrowserRuntimeReceipt.fileCount,
535
- browserTotalBytes:sdkBrowserRuntimeReceipt.totalBytes,
536
- browserContentSha256:sdkBrowserRuntimeReceipt.contentSha256,
537
- sharedFiles:Object.freeze(retained),
538
- sharedFileCount:retained.length,
539
- sharedTotalBytes:retained.reduce((total,file)=>total+file.bytes,0),
540
- sharedPayloadContentSha256:sharedPayloadSnapshot.contentSha256
541
- });
542
- await emit(onEvent,{
543
- type:'runtime.snapshot.verified',
544
- contentSha256:receipt.contentSha256,
545
- fileCount:receipt.fileCount,
546
- totalBytes:receipt.totalBytes,
547
- browserContentSha256:receipt.browserContentSha256,
548
- browserFileCount:receipt.browserFileCount,
549
- browserTotalBytes:receipt.browserTotalBytes
550
- });
551
- return Object.freeze({
552
- receipt,
553
- runtimeVerificationState:Object.freeze({
554
- runtimeReceipt,
555
- sdkBrowserRuntimeReceipt,
556
- workspaceRuntimeReceipt
557
- })
558
- });
559
- }
560
-
561
274
  async function validatePreparedRuntime(prepared,{signal}={}){
562
- if(prepared.workspaceMode==='external'){
563
- await authenticateRuntimeReceipt(prepared.runtimeReceipt,{
564
- runtimeRoot:prepared.runtimeRoot,
565
- signal
566
- });
567
- await authenticateSdkBrowserRuntimeReceipt(prepared.sdkBrowserRuntimeReceipt,{
568
- browserRuntimeRoot:prepared.browserRuntimeRoot,
569
- signal
570
- });
571
- return authenticateWorkspaceRuntimeReceipt(prepared.workspaceRuntimeReceipt,{
572
- workspaceRoot:prepared.workspaceRoot,
573
- signal
574
- });
575
- }
576
275
  const validation=await validateWorkspace({
577
276
  workspaceRoot:prepared.workspaceRoot,
578
277
  appId:prepared.appId,
579
278
  signal
580
279
  });
581
- if(validation.workspaceMode!=='integrated'){
582
- throw new ArcaneError(ERROR_CODES.workspaceInvalid,'The integrated Arcane workspace profile changed during the operation.');
280
+ if(validation.workspaceMode!==prepared.workspaceMode){
281
+ throw new ArcaneError(ERROR_CODES.workspaceInvalid,'The Arcane workspace profile changed during the operation.');
583
282
  }
584
283
  return validation;
585
284
  }
@@ -587,21 +286,35 @@ async function validatePreparedRuntime(prepared,{signal}={}){
587
286
  async function refreshPreparedImportMap(prepared,{signal,onEvent,workspaceOperationLease}={}){
588
287
  if(prepared.workspaceMode==='integrated'
589
288
  &&prepared.validation.config.browserRuntimeLayout==='integrated-legacy'){
590
- const receipt=Object.freeze({
289
+ const result={
591
290
  appId:prepared.appId,
592
291
  skipped:true,
593
292
  compatibility:'integrated-legacy',
594
293
  reason:'The canonical integrated Arcane OS root retains its physical two-route browser runtime.'
595
- });
596
- await emit(onEvent,{type:'import-map.compatibility.skipped',...receipt});
597
- return receipt;
294
+ };
295
+ await emit(onEvent,{type:'import-map.compatibility.skipped',...result});
296
+ return result;
297
+ }
298
+ const manifest=prepared.validation.app.manifest;
299
+ const inspected=await inspectPackagedApp({
300
+ workspaceRoot:prepared.workspaceRoot,
301
+ appId:prepared.appId,
302
+ signal
303
+ });
304
+ if(inspected.entry!==manifest.entry
305
+ ||JSON.stringify(inspected.include)!==JSON.stringify(manifest.include)
306
+ ||JSON.stringify(inspected.exclude)!==JSON.stringify(manifest.exclude)){
307
+ throw new ArcaneError(
308
+ ERROR_CODES.workspaceInvalid,
309
+ 'The selected application package descriptor changed before import-map refresh.'
310
+ );
598
311
  }
599
312
  return generateImportMap({
600
313
  workspaceRoot:prepared.workspaceRoot,
601
314
  appId:prepared.appId,
602
315
  appRoot:prepared.appRoot,
603
- entry:prepared.validation.app.manifest.entry,
604
- workspaceRuntimeReceipt:prepared.workspaceRuntimeReceipt,
316
+ entry:manifest.entry,
317
+ documents:inspected.browserDocuments,
605
318
  workspaceOperationLease,
606
319
  signal,
607
320
  onEvent
@@ -633,6 +346,33 @@ export async function initializeApplication(options={}){
633
346
  return initWorkspace(options);
634
347
  }
635
348
 
349
+ export async function upgradeApplication(options={}){
350
+ assertApplicationScope(options,'Workspace upgrade');
351
+ const selected=await resolveWorkspace({
352
+ workspaceRoot:options.workspaceRoot,
353
+ appId:options.appId
354
+ });
355
+ if(selected.config.workspaceMode!=='external'){
356
+ throw new ArcaneError(
357
+ ERROR_CODES.policyDenied,
358
+ 'Workspace upgrade is available only to installed-SDK external workspaces.'
359
+ );
360
+ }
361
+ const result=await runProcess('npm',['upgrade'],{
362
+ cwd:selected.workspaceRoot,
363
+ signal:options.signal,
364
+ onEvent:options.onEvent
365
+ });
366
+ return {
367
+ schemaVersion:1,
368
+ kind:'arcane-application-upgrade',
369
+ workspaceRoot:selected.workspaceRoot,
370
+ workspaceMode:selected.config.workspaceMode,
371
+ appId:selected.appId,
372
+ ...result
373
+ };
374
+ }
375
+
636
376
  export async function doctorApplication(options={}){
637
377
  const result=await runDoctor(options);
638
378
  if(!result.ok){
@@ -645,6 +385,18 @@ export async function doctorApplication(options={}){
645
385
  return result;
646
386
  }
647
387
 
388
+ async function runPreparedApplicationTests(prepared,options={}){
389
+ throwIfAborted(options.signal);
390
+ return runApplicationTests({
391
+ workspaceRoot:prepared.workspaceRoot,
392
+ workspaceMode:prepared.workspaceMode,
393
+ appId:prepared.appId,
394
+ appRoot:prepared.appRoot,
395
+ signal:options.signal,
396
+ onEvent:options.onEvent
397
+ });
398
+ }
399
+
648
400
  export async function testApplication(options={}){
649
401
  throwIfAborted(options.signal);
650
402
  if(operationScope(options)==='shared'){
@@ -656,96 +408,8 @@ export async function testApplication(options={}){
656
408
  }
657
409
  return executeIntegratedSharedOperation('focused-test',options);
658
410
  }
659
- const workspace=options.workspaceRoot&&options.appId&&options.appRoot
660
- ?{
661
- workspaceRoot:options.workspaceRoot,
662
- workspaceMode:options.workspaceMode
663
- ??(await inspectWorkspaceProfile(options.workspaceRoot)).workspaceMode,
664
- appId:options.appId,
665
- appRoot:options.appRoot
666
- }
667
- :await selectedWorkspace(options);
668
- const files=new Set();
669
- if(workspace.workspaceMode==='external'){
670
- await collectTests(path.join(workspace.workspaceRoot,'test'),files,options.signal);
671
- }
672
- if(workspace.appRoot){
673
- await collectTests(path.join(workspace.appRoot,'test'),files,options.signal);
674
- }
675
- const testFiles=[...files].sort();
676
- if(testFiles.length===0){
677
- await emit(options.onEvent,{
678
- type:'test.skipped',
679
- message:'No JavaScript test files were found.',
680
- data:{workspaceRoot:workspace.workspaceRoot,appId:workspace.appId}
681
- });
682
- return {...workspace,passed:true,skipped:true,testFiles:[]};
683
- }
684
- const outputs=[];
685
- const failures=[];
686
- let failureOutputBytes=0;
687
- const perFileFailureOutputBytes=Math.min(
688
- MAX_TEST_FAILURE_STREAM_BYTES*2,
689
- Math.floor(MAX_TEST_FAILURE_AGGREGATE_BYTES/testFiles.length)
690
- );
691
- for(const testFile of testFiles){
692
- throwIfAborted(options.signal);
693
- const result=await runProcess(
694
- process.execPath,
695
- [TEST_RUNNER_PATH,testFile],
696
- {
697
- cwd:workspace.workspaceRoot,
698
- signal:options.signal,
699
- onEvent:options.onEvent,
700
- allowNonzero:true
701
- }
702
- );
703
- if(result.code===0){
704
- if(result.stdout.trim())outputs.push(result.stdout.trim());
705
- }else if(result.code===1){
706
- const captured=captureFailedTest(
707
- testFile,
708
- result,
709
- workspace.workspaceRoot,
710
- Math.min(
711
- perFileFailureOutputBytes,
712
- MAX_TEST_FAILURE_AGGREGATE_BYTES-failureOutputBytes
713
- )
714
- );
715
- failures.push(captured.failure);
716
- failureOutputBytes+=captured.bytes;
717
- }else if(result.code!==0){
718
- throw new ArcaneError(
719
- ERROR_CODES.operationFailed,
720
- `The isolated test runner exited with code ${String(result.code)} for ${path.basename(testFile)}.`,
721
- {details:{testFile,result}}
722
- );
723
- }
724
- }
725
- if(failures.length>0){
726
- throw new ArcaneError(
727
- ERROR_CODES.operationFailed,
728
- failedTestMessage(failures),
729
- {
730
- details:{
731
- testFiles:failures.map(failure=>failure.testFile),
732
- failures,
733
- outputBytes:failureOutputBytes,
734
- outputLimitBytes:MAX_TEST_FAILURE_AGGREGATE_BYTES,
735
- outputTruncated:failures.some(
736
- failure=>failure.stdoutTruncated||failure.stderrTruncated
737
- )
738
- }
739
- }
740
- );
741
- }
742
- return {
743
- ...workspace,
744
- passed:true,
745
- skipped:false,
746
- testFiles:testFiles.map(file=>path.relative(workspace.workspaceRoot,file).replaceAll('\\','/')),
747
- output:outputs.join('\n')
748
- };
411
+ const prepared=await preparedWorkspace({...options,allowMissingManagedImportMap:true});
412
+ return runPreparedApplicationTests(prepared,options);
749
413
  }
750
414
 
751
415
  export async function checkApplication(options={}){
@@ -755,10 +419,15 @@ export async function checkApplication(options={}){
755
419
  }
756
420
  return executeIntegratedSharedOperation('development-check',options);
757
421
  }
758
- const prepared=await preparedWorkspace(options);
422
+ const prepared=await preparedWorkspace({...options,allowMissingManagedImportMap:true});
759
423
  const tests=options.skipTests
760
- ?{passed:true,skipped:true,testFiles:[]}
761
- :await testApplication({...options,...prepared});
424
+ ?{
425
+ passed:true,
426
+ skipped:true,
427
+ testFiles:[],
428
+ output:''
429
+ }
430
+ :await runPreparedApplicationTests(prepared,options);
762
431
  await validatePreparedRuntime(prepared,{signal:options.signal});
763
432
  return {
764
433
  ok:true,
@@ -766,17 +435,10 @@ export async function checkApplication(options={}){
766
435
  workspaceRoot:prepared.workspaceRoot,
767
436
  appId:prepared.appId,
768
437
  descriptorSource:prepared.descriptorSource,
769
- runtime:prepared.runtimeReceipt
770
- ?{
771
- mode:'sdk',
772
- manifestSha256:prepared.runtimeReceipt.manifestSha256,
773
- contentSha256:prepared.runtimeReceipt.contentSha256,
774
- fileCount:prepared.runtimeReceipt.fileCount
775
- }
776
- :{
777
- mode:'workspace',
778
- sourceRoot:'arcane'
779
- },
438
+ runtime:{
439
+ mode:prepared.workspaceMode==='external'?'sdk':'workspace',
440
+ sourceRoot:'arcane'
441
+ },
780
442
  checks:prepared.validation.checks,
781
443
  tests
782
444
  };
@@ -798,7 +460,6 @@ export async function developApplication(options={}){
798
460
  workspaceRoot:prepared.workspaceRoot,
799
461
  appId:prepared.appId,
800
462
  mode:'source',
801
- workspaceRuntimeReceipt:prepared.workspaceRuntimeReceipt,
802
463
  workspaceMode:prepared.workspaceMode,
803
464
  ...(options.sdkRuntimeSourceRoot===undefined?{}:{
804
465
  sdkRuntimeSourceRoot:options.sdkRuntimeSourceRoot
@@ -819,23 +480,22 @@ export async function packageApplication(options={}){
819
480
  });
820
481
  const release=await ownedWork(
821
482
  'package',
822
- ({signal,onEvent,workspaceOperationLease})=>packageApp({
483
+ async({signal,onEvent,workspaceOperationLease})=>{
484
+ return packageApp({
823
485
  workspaceRoot:prepared.workspaceRoot,
824
486
  appId:prepared.appId,
825
487
  dryRun:Boolean(options.dryRun),
826
488
  signal,
827
489
  onEvent,
828
- workspaceOperationLease,
829
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
830
- validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
831
- }),
490
+ workspaceOperationLease
491
+ });
492
+ },
832
493
  {...options,workspaceRoot:prepared.workspaceRoot}
833
494
  );
834
495
  return {
835
496
  workspaceRoot:prepared.workspaceRoot,
836
497
  workspaceMode:prepared.workspaceMode,
837
498
  appId:prepared.appId,
838
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
839
499
  release
840
500
  };
841
501
  }
@@ -848,7 +508,6 @@ export async function verifyApplication(options={}){
848
508
  ({signal,onEvent})=>verifyApp({
849
509
  workspaceRoot:prepared.workspaceRoot,
850
510
  appId:prepared.appId,
851
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
852
511
  signal,
853
512
  onEvent
854
513
  }),
@@ -859,7 +518,6 @@ export async function verifyApplication(options={}){
859
518
  workspaceRoot:prepared.workspaceRoot,
860
519
  workspaceMode:prepared.workspaceMode,
861
520
  appId:prepared.appId,
862
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
863
521
  release
864
522
  };
865
523
  }
@@ -876,19 +534,18 @@ export async function bundleApplication(options={}){
876
534
  const verified=await verifyApp({
877
535
  workspaceRoot:prepared.workspaceRoot,
878
536
  appId:prepared.appId,
879
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
880
537
  signal,
881
538
  onEvent
882
539
  });
883
540
  await validatePreparedRuntime(prepared,{signal});
884
- const releaseRoot=verified.receipt.canonicalLocation;
541
+ const releaseRoot=verified.outputRoot;
885
542
  const outputPath=options.artifactPath??path.join(
886
543
  path.dirname(releaseRoot),
887
544
  `${prepared.appId}-${verified.version}${APP_BUNDLE_EXTENSION}`
888
545
  );
889
546
  return createAppReleaseBundle({
890
- receipt:verified.receipt,
891
547
  releaseRoot,
548
+ appDescriptor:prepared.descriptor,
892
549
  outputPath,
893
550
  overwrite:options.overwrite,
894
551
  signal,
@@ -901,7 +558,6 @@ export async function bundleApplication(options={}){
901
558
  workspaceRoot:prepared.workspaceRoot,
902
559
  workspaceMode:prepared.workspaceMode,
903
560
  appId:prepared.appId,
904
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
905
561
  bundle
906
562
  };
907
563
  }
@@ -1059,19 +715,6 @@ export function assertIntegratedPortableToolchain(options={}){
1059
715
  return assertIntegratedNativeToolchain({...options,target:'portable'});
1060
716
  }
1061
717
 
1062
- export function assertNativeApplicationToolchainCompatibility({prepared,toolchainReceipt}={}){
1063
- return assertNativeToolchainCompatibility({
1064
- appDescriptor:prepared?.descriptor,
1065
- toolchainReceipt,
1066
- minimumCoreVersion:prepared?.runtimeReceipt?.source?.bundleVersion
1067
- ??ARCANE_MACHINE_BUNDLE_VERSION
1068
- });
1069
- }
1070
-
1071
- export function assertPortableToolchainCompatibility(options={}){
1072
- return assertNativeApplicationToolchainCompatibility(options);
1073
- }
1074
-
1075
718
  export async function verifyNativeArtifact(options={}){
1076
719
  const {target,adapter}=targetSelection(options);
1077
720
  const targetDescription=await adapter.describe();
@@ -1106,7 +749,7 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1106
749
  if(JSON.stringify(selected.descriptor)!==JSON.stringify(prepared.descriptor)){
1107
750
  nativeDependencyError(
1108
751
  `The selected app ${prepared.appId} descriptor changed during native build preflight.`,
1109
- ERROR_CODES.integrityFailed
752
+ ERROR_CODES.workspaceInvalid
1110
753
  );
1111
754
  }
1112
755
  if(!prepared.descriptor.targets.includes(target)){
@@ -1118,7 +761,6 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1118
761
 
1119
762
  const visiting=new Set([prepared.appId]);
1120
763
  const visited=new Set();
1121
- const discovered=new Set();
1122
764
  const dependencies=[];
1123
765
  function visit(descriptor){
1124
766
  for(const dependencyId of descriptor.native.bundledApps){
@@ -1138,10 +780,6 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1138
780
  ERROR_CODES.targetUnavailable
1139
781
  );
1140
782
  }
1141
- if(discovered.size>=64){
1142
- nativeDependencyError('A native app dependency closure may contain at most 64 apps.');
1143
- }
1144
- discovered.add(dependencyId);
1145
783
  visiting.add(dependencyId);
1146
784
  visit(dependency.descriptor);
1147
785
  visiting.delete(dependencyId);
@@ -1162,13 +800,13 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1162
800
  signal,
1163
801
  onEvent
1164
802
  });
1165
- validated.push(Object.freeze({
803
+ validated.push({
1166
804
  ...dependency,
1167
805
  descriptor:validation.app.descriptor,
1168
806
  validation
1169
- }));
807
+ });
1170
808
  }
1171
- return Object.freeze(validated);
809
+ return validated;
1172
810
  }
1173
811
 
1174
812
  async function externalWorkspaceProtectedRoots(prepared,{signal}={}){
@@ -1222,45 +860,28 @@ function pathsOverlap(left,right){
1222
860
  }
1223
861
 
1224
862
  async function packageNativeRelease(prepared,app,{
1225
- sharedPayloadSnapshot,
1226
863
  workspaceOperationLease,
1227
864
  signal,
1228
865
  onEvent
1229
866
  }={}){
1230
- const sourceState={
1231
- ...prepared,
1232
- appId:app.appId,
1233
- appRoot:app.appRoot,
1234
- descriptor:app.descriptor,
1235
- validation:app.validation??prepared.validation
1236
- };
1237
867
  const release=await packageApp({
1238
868
  workspaceRoot:prepared.workspaceRoot,
1239
869
  appId:app.appId,
1240
- sharedPayloadSnapshot,
1241
- runtimeVerificationState:prepared.runtimeVerificationState??undefined,
1242
870
  workspaceOperationLease,
1243
871
  signal,
1244
- onEvent,
1245
- validateSourceState:({signal:validationSignal}={})=>validateDiscoveredApplication({
1246
- workspaceRoot:sourceState.workspaceRoot,
1247
- workspaceMode:sourceState.workspaceMode,
1248
- workspaceConfig:prepared.validation.config,
1249
- app,
1250
- signal:validationSignal
1251
- })
872
+ onEvent
1252
873
  });
1253
- return Object.freeze({
874
+ return {
1254
875
  appId:app.appId,
1255
876
  appRoot:app.appRoot,
1256
877
  descriptor:app.descriptor,
1257
878
  release,
1258
- nativeInput:Object.freeze({
879
+ nativeInput:{
1259
880
  appDescriptor:app.descriptor,
1260
- appReleaseRoot:path.resolve(prepared.workspaceRoot,release.output),
1261
- appReleaseReceipt:release.receipt
1262
- })
1263
- });
881
+ appReleaseRoot:release.outputRoot??path.resolve(prepared.workspaceRoot,release.output),
882
+ release:{manifest:release.manifest,files:[...release.files]}
883
+ }
884
+ };
1264
885
  }
1265
886
 
1266
887
  async function executePairedNativeBuild(options,adapter,{
@@ -1269,12 +890,7 @@ async function executePairedNativeBuild(options,adapter,{
1269
890
  workspaceOperationLease
1270
891
  }={}){
1271
892
  const target=options.target??options.targetRequest?.target;
1272
- const initialPrepared=await preparedWorkspace({
1273
- ...options,
1274
- deferRuntimeVerification:true,
1275
- signal,
1276
- onEvent
1277
- });
893
+ const initialPrepared=await preparedWorkspace({...options,signal,onEvent});
1278
894
  assertIntegratedNativeToolchain({
1279
895
  target,
1280
896
  workspaceMode:initialPrepared.workspaceMode,
@@ -1284,7 +900,7 @@ async function executePairedNativeBuild(options,adapter,{
1284
900
  if(options.dryRun){
1285
901
  throw new ArcaneError(
1286
902
  ERROR_CODES.usage,
1287
- `${target} native build does not support --dry-run because verified app release receipts are required.`
903
+ `${target} native build does not support --dry-run because the native provider needs materialized app files.`
1288
904
  );
1289
905
  }
1290
906
  const requestedOutputRoot=resolveNativeBuildOutputRoot({
@@ -1302,31 +918,7 @@ async function executePairedNativeBuild(options,adapter,{
1302
918
  );
1303
919
  }
1304
920
  const dependencyApps=await nativeDependencyClosure(initialPrepared,{target,signal,onEvent});
1305
- const sharedPayloadIds=[...new Set([
1306
- ...initialPrepared.validation.app.manifest.shared,
1307
- ...dependencyApps.flatMap(app=>app.manifest.shared)
1308
- ])].sort((left,right)=>left.localeCompare(right,'en'));
1309
- const sharedPayloadSnapshot=await prepareSharedPayloadSnapshot({
1310
- workspaceRoot:initialPrepared.workspaceRoot,
1311
- sharedPayloadIds,
1312
- signal,
1313
- onEvent
1314
- });
1315
- const externalRuntimeState=initialPrepared.workspaceMode==='external'
1316
- ?await externalRuntimeSnapshotReceipt(
1317
- initialPrepared,
1318
- sharedPayloadSnapshot,
1319
- sharedPayloadIds,
1320
- {signal,onEvent}
1321
- )
1322
- :null;
1323
- const prepared={
1324
- ...initialPrepared,
1325
- runtimeReceipt:externalRuntimeState?.receipt??null,
1326
- runtimeVerificationState:externalRuntimeState?.runtimeVerificationState??null,
1327
- workspaceRuntimeReceipt:
1328
- externalRuntimeState?.runtimeVerificationState.workspaceRuntimeReceipt??null
1329
- };
921
+ const prepared=initialPrepared;
1330
922
  const selectedRelease=await packageNativeRelease(prepared,{
1331
923
  appId:prepared.appId,
1332
924
  appRoot:prepared.appRoot,
@@ -1335,16 +927,16 @@ async function executePairedNativeBuild(options,adapter,{
1335
927
  descriptorSource:prepared.validation.app.descriptorSource,
1336
928
  descriptorPath:prepared.validation.app.descriptorPath,
1337
929
  validation:prepared.validation
1338
- },{sharedPayloadSnapshot,workspaceOperationLease,signal,onEvent});
930
+ },{workspaceOperationLease,signal,onEvent});
1339
931
  const dependencyReleases=[];
1340
932
  for(const dependency of dependencyApps){
1341
933
  dependencyReleases.push(await packageNativeRelease(
1342
934
  prepared,
1343
935
  dependency,
1344
- {sharedPayloadSnapshot,workspaceOperationLease,signal,onEvent}
936
+ {workspaceOperationLease,signal,onEvent}
1345
937
  ));
1346
938
  }
1347
- const toolchainReceipt=await adapter.prepare({
939
+ const toolchain=await adapter.prepare({
1348
940
  toolchainRoot:options.toolchainRoot,
1349
941
  targetRequest:options.targetRequest,
1350
942
  signal,
@@ -1354,26 +946,24 @@ async function executePairedNativeBuild(options,adapter,{
1354
946
  const built=await adapter.build({
1355
947
  nativeBuilder:options.nativeBuilder,
1356
948
  toolchainRoot:options.toolchainRoot,
1357
- toolchainReceipt,
949
+ toolchain,
1358
950
  ...selectedRelease.nativeInput,
1359
951
  dependencyReleases:dependencyReleases.map(item=>item.nativeInput),
1360
- providerGeneration:options.providerGeneration??options.nativeBuilder?.providerGeneration,
1361
- minimumCoreVersion:prepared.runtimeReceipt?.source?.bundleVersion
1362
- ??ARCANE_MACHINE_BUNDLE_VERSION,
952
+ minimumCoreVersion:ARCANE_MACHINE_BUNDLE_VERSION,
1363
953
  protectedRoots,
1364
954
  outputRoot,
1365
955
  targetRequest:options.targetRequest,
1366
956
  signal,
1367
957
  onEvent
1368
958
  });
1369
- return Object.freeze({
959
+ return {
1370
960
  prepared,
1371
961
  outputRoot,
1372
- toolchainReceipt,
962
+ toolchain,
1373
963
  selectedRelease,
1374
- dependencyReleases:Object.freeze(dependencyReleases),
964
+ dependencyReleases,
1375
965
  built
1376
- });
966
+ };
1377
967
  }
1378
968
 
1379
969
  function nativeBuildResult(assembly){
@@ -1383,9 +973,8 @@ function nativeBuildResult(assembly){
1383
973
  workspaceRoot:prepared.workspaceRoot,
1384
974
  workspaceMode:prepared.workspaceMode,
1385
975
  appId:prepared.appId,
1386
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
1387
976
  release:assembly.selectedRelease.release,
1388
- dependencyReleases:assembly.dependencyReleases.map(item=>Object.freeze({
977
+ dependencyReleases:assembly.dependencyReleases.map(item=>({
1389
978
  appId:item.appId,
1390
979
  release:item.release
1391
980
  }))
@@ -1395,7 +984,7 @@ function nativeBuildResult(assembly){
1395
984
  function usesWorkspaceNativeAssembly(options){
1396
985
  return options.nativeBuilder!=null
1397
986
  &&typeof options.workspaceRoot==='string'
1398
- &&options.appReleaseReceipt==null
987
+ &&options.release==null
1399
988
  &&options.appReleaseRoot==null
1400
989
  &&options.appDescriptor==null;
1401
990
  }
@@ -1431,18 +1020,15 @@ export async function buildApplication(options={}){
1431
1020
  ({signal,onEvent,workspaceOperationLease})=>buildTarget({
1432
1021
  ...options,
1433
1022
  ...prepared,
1434
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
1435
1023
  signal,
1436
1024
  onEvent,
1437
- workspaceOperationLease,
1438
- validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
1025
+ workspaceOperationLease
1439
1026
  }),
1440
1027
  {...options,workspaceRoot:prepared.workspaceRoot}
1441
1028
  );
1442
1029
  return {
1443
1030
  ...result,
1444
- workspaceMode:prepared.workspaceMode,
1445
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null
1031
+ workspaceMode:prepared.workspaceMode
1446
1032
  };
1447
1033
  }
1448
1034
 
@@ -1463,15 +1049,15 @@ export async function runApplication(options={}){
1463
1049
  return adapter.run({...selectedOptions,target});
1464
1050
  }
1465
1051
  if(target!=='browser'){
1466
- if(usesWorkspaceNativeAssembly(selectedOptions)&&selectedOptions.artifactReceipt==null){
1052
+ if(usesWorkspaceNativeAssembly(selectedOptions)&&selectedOptions.artifact==null){
1467
1053
  return ownedWork(
1468
1054
  'run',
1469
1055
  async context=>{
1470
1056
  const assembly=await executePairedNativeBuild(selectedOptions,adapter,context);
1471
1057
  const launched=await adapter.run({
1472
1058
  toolchainRoot:selectedOptions.toolchainRoot,
1473
- toolchainReceipt:assembly.toolchainReceipt,
1474
- artifactReceipt:assembly.built.artifactReceipt,
1059
+ toolchain:assembly.toolchain,
1060
+ artifact:assembly.built.artifact,
1475
1061
  targetRequest:selectedOptions.targetRequest,
1476
1062
  signal:context.signal,
1477
1063
  onEvent:context.onEvent
@@ -1491,7 +1077,6 @@ export async function runApplication(options={}){
1491
1077
  return runTarget({
1492
1078
  ...selectedOptions,
1493
1079
  ...prepared,
1494
- runtimeVerificationState:forwardedRuntimeVerificationState(selectedOptions,prepared),
1495
1080
  target
1496
1081
  });
1497
1082
  }
@@ -1527,6 +1112,7 @@ export async function executeOperation(command,options={}){
1527
1112
  const operations={
1528
1113
  new:createApplication,
1529
1114
  init:initializeApplication,
1115
+ upgrade:upgradeApplication,
1530
1116
  doctor:doctorApplication,
1531
1117
  'import-map':importMapApplication,
1532
1118
  dev:developApplication,
@@ -1555,10 +1141,11 @@ export async function executeOperation(command,options={}){
1555
1141
  }
1556
1142
 
1557
1143
  export function createToolchain(defaults={}){
1558
- return Object.freeze({
1144
+ return {
1559
1145
  execute:(command,options={})=>executeOperation(command,{...defaults,...options}),
1560
1146
  create:options=>createApplication({...defaults,...options}),
1561
1147
  init:options=>initializeApplication({...defaults,...options}),
1148
+ upgrade:options=>upgradeApplication({...defaults,...options}),
1562
1149
  doctor:options=>doctorApplication({...defaults,...options}),
1563
1150
  importMap:options=>importMapApplication({...defaults,...options}),
1564
1151
  dev:options=>developApplication({...defaults,...options}),
@@ -1578,5 +1165,5 @@ export function createToolchain(defaults={}){
1578
1165
  mail:options=>executeMailCommand({...defaults,...options}),
1579
1166
  targets:options=>describeTargets({...defaults,...options}),
1580
1167
  repository:options=>repositoryApplication({...defaults,...options})
1581
- });
1168
+ };
1582
1169
  }