arcane-os 0.3.1 → 0.3.3

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 +855 -895
  5. package/browser-runtime/ai/browser-speech-providers.mjs +80 -204
  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 -148
  11. package/browser-runtime/ai/speech-worker-runtime.mjs +642 -374
  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 +113 -69
  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 +1042 -427
  37. package/runtime/arcane/modules/AIProviderRuntime.js +618 -359
  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 +19 -149
  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 +42 -327
  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 +48 -66
  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 +492 -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 +48 -79
  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 +55 -135
  103. package/src/testing-loader.mjs +164 -0
  104. package/src/testing.mjs +1 -1
  105. package/src/toolchain.mjs +133 -544
  106. package/src/update-check.mjs +26 -64
  107. package/src/workspace-operation-lock.mjs +139 -430
  108. package/src/workspace-runtime.mjs +109 -1558
  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 -185
  120. package/docs/reference/ai/browser-speech-package-authority.json +0 -835
  121. package/docs/reference/ai/browser-speech.md +0 -1295
  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 -719
  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 -2965
  150. package/docs/reference/sdk-api.md +0 -6698
  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,37 @@ 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.map(function selectBrowserDocumentPath(document){
318
+ return document.path;
319
+ }),
605
320
  workspaceOperationLease,
606
321
  signal,
607
322
  onEvent
@@ -633,6 +348,33 @@ export async function initializeApplication(options={}){
633
348
  return initWorkspace(options);
634
349
  }
635
350
 
351
+ export async function upgradeApplication(options={}){
352
+ assertApplicationScope(options,'Workspace upgrade');
353
+ const selected=await resolveWorkspace({
354
+ workspaceRoot:options.workspaceRoot,
355
+ appId:options.appId
356
+ });
357
+ if(selected.config.workspaceMode!=='external'){
358
+ throw new ArcaneError(
359
+ ERROR_CODES.policyDenied,
360
+ 'Workspace upgrade is available only to installed-SDK external workspaces.'
361
+ );
362
+ }
363
+ const result=await runProcess('npm',['upgrade'],{
364
+ cwd:selected.workspaceRoot,
365
+ signal:options.signal,
366
+ onEvent:options.onEvent
367
+ });
368
+ return {
369
+ schemaVersion:1,
370
+ kind:'arcane-application-upgrade',
371
+ workspaceRoot:selected.workspaceRoot,
372
+ workspaceMode:selected.config.workspaceMode,
373
+ appId:selected.appId,
374
+ ...result
375
+ };
376
+ }
377
+
636
378
  export async function doctorApplication(options={}){
637
379
  const result=await runDoctor(options);
638
380
  if(!result.ok){
@@ -645,6 +387,18 @@ export async function doctorApplication(options={}){
645
387
  return result;
646
388
  }
647
389
 
390
+ async function runPreparedApplicationTests(prepared,options={}){
391
+ throwIfAborted(options.signal);
392
+ return runApplicationTests({
393
+ workspaceRoot:prepared.workspaceRoot,
394
+ workspaceMode:prepared.workspaceMode,
395
+ appId:prepared.appId,
396
+ appRoot:prepared.appRoot,
397
+ signal:options.signal,
398
+ onEvent:options.onEvent
399
+ });
400
+ }
401
+
648
402
  export async function testApplication(options={}){
649
403
  throwIfAborted(options.signal);
650
404
  if(operationScope(options)==='shared'){
@@ -656,96 +410,8 @@ export async function testApplication(options={}){
656
410
  }
657
411
  return executeIntegratedSharedOperation('focused-test',options);
658
412
  }
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
- };
413
+ const prepared=await preparedWorkspace({...options,allowMissingManagedImportMap:true});
414
+ return runPreparedApplicationTests(prepared,options);
749
415
  }
750
416
 
751
417
  export async function checkApplication(options={}){
@@ -755,10 +421,15 @@ export async function checkApplication(options={}){
755
421
  }
756
422
  return executeIntegratedSharedOperation('development-check',options);
757
423
  }
758
- const prepared=await preparedWorkspace(options);
424
+ const prepared=await preparedWorkspace({...options,allowMissingManagedImportMap:true});
759
425
  const tests=options.skipTests
760
- ?{passed:true,skipped:true,testFiles:[]}
761
- :await testApplication({...options,...prepared});
426
+ ?{
427
+ passed:true,
428
+ skipped:true,
429
+ testFiles:[],
430
+ output:''
431
+ }
432
+ :await runPreparedApplicationTests(prepared,options);
762
433
  await validatePreparedRuntime(prepared,{signal:options.signal});
763
434
  return {
764
435
  ok:true,
@@ -766,17 +437,10 @@ export async function checkApplication(options={}){
766
437
  workspaceRoot:prepared.workspaceRoot,
767
438
  appId:prepared.appId,
768
439
  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
- },
440
+ runtime:{
441
+ mode:prepared.workspaceMode==='external'?'sdk':'workspace',
442
+ sourceRoot:'arcane'
443
+ },
780
444
  checks:prepared.validation.checks,
781
445
  tests
782
446
  };
@@ -798,7 +462,6 @@ export async function developApplication(options={}){
798
462
  workspaceRoot:prepared.workspaceRoot,
799
463
  appId:prepared.appId,
800
464
  mode:'source',
801
- workspaceRuntimeReceipt:prepared.workspaceRuntimeReceipt,
802
465
  workspaceMode:prepared.workspaceMode,
803
466
  ...(options.sdkRuntimeSourceRoot===undefined?{}:{
804
467
  sdkRuntimeSourceRoot:options.sdkRuntimeSourceRoot
@@ -819,23 +482,22 @@ export async function packageApplication(options={}){
819
482
  });
820
483
  const release=await ownedWork(
821
484
  'package',
822
- ({signal,onEvent,workspaceOperationLease})=>packageApp({
485
+ async({signal,onEvent,workspaceOperationLease})=>{
486
+ return packageApp({
823
487
  workspaceRoot:prepared.workspaceRoot,
824
488
  appId:prepared.appId,
825
489
  dryRun:Boolean(options.dryRun),
826
490
  signal,
827
491
  onEvent,
828
- workspaceOperationLease,
829
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
830
- validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
831
- }),
492
+ workspaceOperationLease
493
+ });
494
+ },
832
495
  {...options,workspaceRoot:prepared.workspaceRoot}
833
496
  );
834
497
  return {
835
498
  workspaceRoot:prepared.workspaceRoot,
836
499
  workspaceMode:prepared.workspaceMode,
837
500
  appId:prepared.appId,
838
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
839
501
  release
840
502
  };
841
503
  }
@@ -848,7 +510,6 @@ export async function verifyApplication(options={}){
848
510
  ({signal,onEvent})=>verifyApp({
849
511
  workspaceRoot:prepared.workspaceRoot,
850
512
  appId:prepared.appId,
851
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
852
513
  signal,
853
514
  onEvent
854
515
  }),
@@ -859,7 +520,6 @@ export async function verifyApplication(options={}){
859
520
  workspaceRoot:prepared.workspaceRoot,
860
521
  workspaceMode:prepared.workspaceMode,
861
522
  appId:prepared.appId,
862
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
863
523
  release
864
524
  };
865
525
  }
@@ -876,19 +536,18 @@ export async function bundleApplication(options={}){
876
536
  const verified=await verifyApp({
877
537
  workspaceRoot:prepared.workspaceRoot,
878
538
  appId:prepared.appId,
879
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
880
539
  signal,
881
540
  onEvent
882
541
  });
883
542
  await validatePreparedRuntime(prepared,{signal});
884
- const releaseRoot=verified.receipt.canonicalLocation;
543
+ const releaseRoot=verified.outputRoot;
885
544
  const outputPath=options.artifactPath??path.join(
886
545
  path.dirname(releaseRoot),
887
546
  `${prepared.appId}-${verified.version}${APP_BUNDLE_EXTENSION}`
888
547
  );
889
548
  return createAppReleaseBundle({
890
- receipt:verified.receipt,
891
549
  releaseRoot,
550
+ appDescriptor:prepared.descriptor,
892
551
  outputPath,
893
552
  overwrite:options.overwrite,
894
553
  signal,
@@ -901,7 +560,6 @@ export async function bundleApplication(options={}){
901
560
  workspaceRoot:prepared.workspaceRoot,
902
561
  workspaceMode:prepared.workspaceMode,
903
562
  appId:prepared.appId,
904
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
905
563
  bundle
906
564
  };
907
565
  }
@@ -1059,19 +717,6 @@ export function assertIntegratedPortableToolchain(options={}){
1059
717
  return assertIntegratedNativeToolchain({...options,target:'portable'});
1060
718
  }
1061
719
 
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
720
  export async function verifyNativeArtifact(options={}){
1076
721
  const {target,adapter}=targetSelection(options);
1077
722
  const targetDescription=await adapter.describe();
@@ -1106,7 +751,7 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1106
751
  if(JSON.stringify(selected.descriptor)!==JSON.stringify(prepared.descriptor)){
1107
752
  nativeDependencyError(
1108
753
  `The selected app ${prepared.appId} descriptor changed during native build preflight.`,
1109
- ERROR_CODES.integrityFailed
754
+ ERROR_CODES.workspaceInvalid
1110
755
  );
1111
756
  }
1112
757
  if(!prepared.descriptor.targets.includes(target)){
@@ -1118,7 +763,6 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1118
763
 
1119
764
  const visiting=new Set([prepared.appId]);
1120
765
  const visited=new Set();
1121
- const discovered=new Set();
1122
766
  const dependencies=[];
1123
767
  function visit(descriptor){
1124
768
  for(const dependencyId of descriptor.native.bundledApps){
@@ -1138,10 +782,6 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1138
782
  ERROR_CODES.targetUnavailable
1139
783
  );
1140
784
  }
1141
- if(discovered.size>=64){
1142
- nativeDependencyError('A native app dependency closure may contain at most 64 apps.');
1143
- }
1144
- discovered.add(dependencyId);
1145
785
  visiting.add(dependencyId);
1146
786
  visit(dependency.descriptor);
1147
787
  visiting.delete(dependencyId);
@@ -1162,13 +802,13 @@ async function nativeDependencyClosure(prepared,{target,signal,onEvent}={}){
1162
802
  signal,
1163
803
  onEvent
1164
804
  });
1165
- validated.push(Object.freeze({
805
+ validated.push({
1166
806
  ...dependency,
1167
807
  descriptor:validation.app.descriptor,
1168
808
  validation
1169
- }));
809
+ });
1170
810
  }
1171
- return Object.freeze(validated);
811
+ return validated;
1172
812
  }
1173
813
 
1174
814
  async function externalWorkspaceProtectedRoots(prepared,{signal}={}){
@@ -1222,45 +862,28 @@ function pathsOverlap(left,right){
1222
862
  }
1223
863
 
1224
864
  async function packageNativeRelease(prepared,app,{
1225
- sharedPayloadSnapshot,
1226
865
  workspaceOperationLease,
1227
866
  signal,
1228
867
  onEvent
1229
868
  }={}){
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
869
  const release=await packageApp({
1238
870
  workspaceRoot:prepared.workspaceRoot,
1239
871
  appId:app.appId,
1240
- sharedPayloadSnapshot,
1241
- runtimeVerificationState:prepared.runtimeVerificationState??undefined,
1242
872
  workspaceOperationLease,
1243
873
  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
- })
874
+ onEvent
1252
875
  });
1253
- return Object.freeze({
876
+ return {
1254
877
  appId:app.appId,
1255
878
  appRoot:app.appRoot,
1256
879
  descriptor:app.descriptor,
1257
880
  release,
1258
- nativeInput:Object.freeze({
881
+ nativeInput:{
1259
882
  appDescriptor:app.descriptor,
1260
- appReleaseRoot:path.resolve(prepared.workspaceRoot,release.output),
1261
- appReleaseReceipt:release.receipt
1262
- })
1263
- });
883
+ appReleaseRoot:release.outputRoot??path.resolve(prepared.workspaceRoot,release.output),
884
+ release:{manifest:release.manifest,files:[...release.files]}
885
+ }
886
+ };
1264
887
  }
1265
888
 
1266
889
  async function executePairedNativeBuild(options,adapter,{
@@ -1269,12 +892,7 @@ async function executePairedNativeBuild(options,adapter,{
1269
892
  workspaceOperationLease
1270
893
  }={}){
1271
894
  const target=options.target??options.targetRequest?.target;
1272
- const initialPrepared=await preparedWorkspace({
1273
- ...options,
1274
- deferRuntimeVerification:true,
1275
- signal,
1276
- onEvent
1277
- });
895
+ const initialPrepared=await preparedWorkspace({...options,signal,onEvent});
1278
896
  assertIntegratedNativeToolchain({
1279
897
  target,
1280
898
  workspaceMode:initialPrepared.workspaceMode,
@@ -1284,7 +902,7 @@ async function executePairedNativeBuild(options,adapter,{
1284
902
  if(options.dryRun){
1285
903
  throw new ArcaneError(
1286
904
  ERROR_CODES.usage,
1287
- `${target} native build does not support --dry-run because verified app release receipts are required.`
905
+ `${target} native build does not support --dry-run because the native provider needs materialized app files.`
1288
906
  );
1289
907
  }
1290
908
  const requestedOutputRoot=resolveNativeBuildOutputRoot({
@@ -1302,31 +920,7 @@ async function executePairedNativeBuild(options,adapter,{
1302
920
  );
1303
921
  }
1304
922
  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
- };
923
+ const prepared=initialPrepared;
1330
924
  const selectedRelease=await packageNativeRelease(prepared,{
1331
925
  appId:prepared.appId,
1332
926
  appRoot:prepared.appRoot,
@@ -1335,16 +929,16 @@ async function executePairedNativeBuild(options,adapter,{
1335
929
  descriptorSource:prepared.validation.app.descriptorSource,
1336
930
  descriptorPath:prepared.validation.app.descriptorPath,
1337
931
  validation:prepared.validation
1338
- },{sharedPayloadSnapshot,workspaceOperationLease,signal,onEvent});
932
+ },{workspaceOperationLease,signal,onEvent});
1339
933
  const dependencyReleases=[];
1340
934
  for(const dependency of dependencyApps){
1341
935
  dependencyReleases.push(await packageNativeRelease(
1342
936
  prepared,
1343
937
  dependency,
1344
- {sharedPayloadSnapshot,workspaceOperationLease,signal,onEvent}
938
+ {workspaceOperationLease,signal,onEvent}
1345
939
  ));
1346
940
  }
1347
- const toolchainReceipt=await adapter.prepare({
941
+ const toolchain=await adapter.prepare({
1348
942
  toolchainRoot:options.toolchainRoot,
1349
943
  targetRequest:options.targetRequest,
1350
944
  signal,
@@ -1354,26 +948,24 @@ async function executePairedNativeBuild(options,adapter,{
1354
948
  const built=await adapter.build({
1355
949
  nativeBuilder:options.nativeBuilder,
1356
950
  toolchainRoot:options.toolchainRoot,
1357
- toolchainReceipt,
951
+ toolchain,
1358
952
  ...selectedRelease.nativeInput,
1359
953
  dependencyReleases:dependencyReleases.map(item=>item.nativeInput),
1360
- providerGeneration:options.providerGeneration??options.nativeBuilder?.providerGeneration,
1361
- minimumCoreVersion:prepared.runtimeReceipt?.source?.bundleVersion
1362
- ??ARCANE_MACHINE_BUNDLE_VERSION,
954
+ minimumCoreVersion:ARCANE_MACHINE_BUNDLE_VERSION,
1363
955
  protectedRoots,
1364
956
  outputRoot,
1365
957
  targetRequest:options.targetRequest,
1366
958
  signal,
1367
959
  onEvent
1368
960
  });
1369
- return Object.freeze({
961
+ return {
1370
962
  prepared,
1371
963
  outputRoot,
1372
- toolchainReceipt,
964
+ toolchain,
1373
965
  selectedRelease,
1374
- dependencyReleases:Object.freeze(dependencyReleases),
966
+ dependencyReleases,
1375
967
  built
1376
- });
968
+ };
1377
969
  }
1378
970
 
1379
971
  function nativeBuildResult(assembly){
@@ -1383,9 +975,8 @@ function nativeBuildResult(assembly){
1383
975
  workspaceRoot:prepared.workspaceRoot,
1384
976
  workspaceMode:prepared.workspaceMode,
1385
977
  appId:prepared.appId,
1386
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null,
1387
978
  release:assembly.selectedRelease.release,
1388
- dependencyReleases:assembly.dependencyReleases.map(item=>Object.freeze({
979
+ dependencyReleases:assembly.dependencyReleases.map(item=>({
1389
980
  appId:item.appId,
1390
981
  release:item.release
1391
982
  }))
@@ -1395,7 +986,7 @@ function nativeBuildResult(assembly){
1395
986
  function usesWorkspaceNativeAssembly(options){
1396
987
  return options.nativeBuilder!=null
1397
988
  &&typeof options.workspaceRoot==='string'
1398
- &&options.appReleaseReceipt==null
989
+ &&options.release==null
1399
990
  &&options.appReleaseRoot==null
1400
991
  &&options.appDescriptor==null;
1401
992
  }
@@ -1431,18 +1022,15 @@ export async function buildApplication(options={}){
1431
1022
  ({signal,onEvent,workspaceOperationLease})=>buildTarget({
1432
1023
  ...options,
1433
1024
  ...prepared,
1434
- runtimeVerificationState:forwardedRuntimeVerificationState(options,prepared),
1435
1025
  signal,
1436
1026
  onEvent,
1437
- workspaceOperationLease,
1438
- validateSourceState:({signal}={})=>validatePreparedRuntime(prepared,{signal})
1027
+ workspaceOperationLease
1439
1028
  }),
1440
1029
  {...options,workspaceRoot:prepared.workspaceRoot}
1441
1030
  );
1442
1031
  return {
1443
1032
  ...result,
1444
- workspaceMode:prepared.workspaceMode,
1445
- runtimeContentSha256:prepared.runtimeReceipt?.contentSha256??null
1033
+ workspaceMode:prepared.workspaceMode
1446
1034
  };
1447
1035
  }
1448
1036
 
@@ -1463,15 +1051,15 @@ export async function runApplication(options={}){
1463
1051
  return adapter.run({...selectedOptions,target});
1464
1052
  }
1465
1053
  if(target!=='browser'){
1466
- if(usesWorkspaceNativeAssembly(selectedOptions)&&selectedOptions.artifactReceipt==null){
1054
+ if(usesWorkspaceNativeAssembly(selectedOptions)&&selectedOptions.artifact==null){
1467
1055
  return ownedWork(
1468
1056
  'run',
1469
1057
  async context=>{
1470
1058
  const assembly=await executePairedNativeBuild(selectedOptions,adapter,context);
1471
1059
  const launched=await adapter.run({
1472
1060
  toolchainRoot:selectedOptions.toolchainRoot,
1473
- toolchainReceipt:assembly.toolchainReceipt,
1474
- artifactReceipt:assembly.built.artifactReceipt,
1061
+ toolchain:assembly.toolchain,
1062
+ artifact:assembly.built.artifact,
1475
1063
  targetRequest:selectedOptions.targetRequest,
1476
1064
  signal:context.signal,
1477
1065
  onEvent:context.onEvent
@@ -1491,7 +1079,6 @@ export async function runApplication(options={}){
1491
1079
  return runTarget({
1492
1080
  ...selectedOptions,
1493
1081
  ...prepared,
1494
- runtimeVerificationState:forwardedRuntimeVerificationState(selectedOptions,prepared),
1495
1082
  target
1496
1083
  });
1497
1084
  }
@@ -1527,6 +1114,7 @@ export async function executeOperation(command,options={}){
1527
1114
  const operations={
1528
1115
  new:createApplication,
1529
1116
  init:initializeApplication,
1117
+ upgrade:upgradeApplication,
1530
1118
  doctor:doctorApplication,
1531
1119
  'import-map':importMapApplication,
1532
1120
  dev:developApplication,
@@ -1555,10 +1143,11 @@ export async function executeOperation(command,options={}){
1555
1143
  }
1556
1144
 
1557
1145
  export function createToolchain(defaults={}){
1558
- return Object.freeze({
1146
+ return {
1559
1147
  execute:(command,options={})=>executeOperation(command,{...defaults,...options}),
1560
1148
  create:options=>createApplication({...defaults,...options}),
1561
1149
  init:options=>initializeApplication({...defaults,...options}),
1150
+ upgrade:options=>upgradeApplication({...defaults,...options}),
1562
1151
  doctor:options=>doctorApplication({...defaults,...options}),
1563
1152
  importMap:options=>importMapApplication({...defaults,...options}),
1564
1153
  dev:options=>developApplication({...defaults,...options}),
@@ -1578,5 +1167,5 @@ export function createToolchain(defaults={}){
1578
1167
  mail:options=>executeMailCommand({...defaults,...options}),
1579
1168
  targets:options=>describeTargets({...defaults,...options}),
1580
1169
  repository:options=>repositoryApplication({...defaults,...options})
1581
- });
1170
+ };
1582
1171
  }