arcane-os 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +8 -8
  3. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +29 -22
  4. package/browser-runtime/ai/ARCANE_AI_BROWSER_SPEECH_COMPONENTS.json +203 -0
  5. package/browser-runtime/ai/browser-kokoro-worker.mjs +11 -2
  6. package/browser-runtime/ai/browser-speech-artifacts.mjs +3230 -397
  7. package/browser-runtime/ai/browser-speech-providers.mjs +1141 -157
  8. package/browser-runtime/ai/browser-speech.mjs +2 -0
  9. package/browser-runtime/ai/browser-whisper-worker.mjs +11 -2
  10. package/browser-runtime/ai/model-controller.mjs +285 -95
  11. package/browser-runtime/ai/speech-worker-client.mjs +247 -32
  12. package/browser-runtime/ai/speech-worker-runtime.mjs +2310 -167
  13. package/browser-runtime/event-manager.mjs +1097 -1
  14. package/docs/architecture.md +2 -2
  15. package/docs/event-manager.md +155 -27
  16. package/docs/reference/README.md +27 -27
  17. package/docs/reference/ai/browser-speech-package-authority.json +835 -0
  18. package/docs/reference/ai/browser-speech.md +1162 -246
  19. package/docs/reference/ai/browser-wasm.md +18 -7
  20. package/docs/reference/availability-and-normalization.md +6 -3
  21. package/docs/reference/behavioral-testing.md +29 -6
  22. package/docs/reference/cli.md +117 -9
  23. package/docs/reference/core/arcane-ai-contracts.md +1 -1
  24. package/docs/reference/event-manager.md +577 -32
  25. package/docs/reference/inventory/package-api.json +478 -2
  26. package/docs/reference/inventory/runtime-components.json +108 -44
  27. package/docs/reference/inventory/runtime-modules.json +131 -53
  28. package/docs/reference/mail.md +316 -0
  29. package/docs/reference/protocols.md +157 -43
  30. package/docs/reference/runtime-components.md +258 -83
  31. package/docs/reference/runtime-modules.md +613 -77
  32. package/docs/reference/sdk-api.md +1014 -25
  33. package/package.json +5 -4
  34. package/runtime/ARCANE_RUNTIME_RELEASE.json +145 -140
  35. package/runtime/arcane/components/app-bar.html +34 -13
  36. package/runtime/arcane/components/assistant-panel.html +110 -57
  37. package/runtime/arcane/components/calculator.html +7 -4
  38. package/runtime/arcane/components/chart.html +58 -17
  39. package/runtime/arcane/components/chat.html +606 -136
  40. package/runtime/arcane/components/conversation-view.html +13 -6
  41. package/runtime/arcane/components/dashboard-config.html +96 -59
  42. package/runtime/arcane/components/data-maintenance.html +69 -14
  43. package/runtime/arcane/components/data-view.html +53 -7
  44. package/runtime/arcane/components/directory-picker.html +118 -32
  45. package/runtime/arcane/components/document-inspector.html +47 -10
  46. package/runtime/arcane/components/file-drop.html +81 -35
  47. package/runtime/arcane/components/file-inspector.html +72 -22
  48. package/runtime/arcane/components/file-manager.html +374 -79
  49. package/runtime/arcane/components/integration-settings.html +12 -5
  50. package/runtime/arcane/components/local-ai-status.html +48 -19
  51. package/runtime/arcane/components/markdown-document.html +161 -68
  52. package/runtime/arcane/components/markdown-editor.html +110 -33
  53. package/runtime/arcane/components/media-embed.html +8 -5
  54. package/runtime/arcane/components/modal.html +15 -5
  55. package/runtime/arcane/components/output-panel.html +28 -23
  56. package/runtime/arcane/components/preferences-form.html +22 -4
  57. package/runtime/arcane/components/record-timeline.html +18 -2
  58. package/runtime/arcane/components/relationship-board.html +23 -3
  59. package/runtime/arcane/components/screen-capture.html +10 -4
  60. package/runtime/arcane/components/source-code-viewer.html +76 -9
  61. package/runtime/arcane/components/source-explanation.html +23 -3
  62. package/runtime/arcane/components/speech.html +462 -384
  63. package/runtime/arcane/components/summary-strip.html +22 -11
  64. package/runtime/arcane/components/table.html +39 -21
  65. package/runtime/arcane/components/task-progress.html +79 -21
  66. package/runtime/arcane/components/terminal-workspace.html +7 -4
  67. package/runtime/arcane/components/theme-editor.html +7 -3
  68. package/runtime/arcane/components/unified-inbox.html +9 -4
  69. package/runtime/arcane/components/voice-transcription.html +639 -98
  70. package/runtime/arcane/components/weather-widget.html +5 -3
  71. package/runtime/arcane/components/web-navigator.html +48 -8
  72. package/runtime/arcane/entities/Chat.js +1 -1
  73. package/runtime/arcane/entities/User.js +110 -23
  74. package/runtime/arcane/modules/AI.js +2109 -130
  75. package/runtime/arcane/modules/AIProviderRuntime.js +720 -13
  76. package/runtime/arcane/modules/AIRuntimeState.js +109 -52
  77. package/runtime/arcane/modules/ApiModelDatabase.js +390 -17
  78. package/runtime/arcane/modules/BrowserTestSuite.js +205 -28
  79. package/runtime/arcane/modules/CalculatorEngine.js +63 -3
  80. package/runtime/arcane/modules/CommunicationAppController.js +588 -28
  81. package/runtime/arcane/modules/CommunicationHub.js +590 -10
  82. package/runtime/arcane/modules/ComponentContracts.js +470 -0
  83. package/runtime/arcane/modules/ConversationTimebox.js +152 -33
  84. package/runtime/arcane/modules/DBLS.js +40 -7
  85. package/runtime/arcane/modules/DBOPFS.js +35 -11
  86. package/runtime/arcane/modules/DataMaintenance.js +12 -2
  87. package/runtime/arcane/modules/Errors.js +65 -7
  88. package/runtime/arcane/modules/HTMLImport.js +198 -14
  89. package/runtime/arcane/modules/LocalAIReadinessController.js +208 -29
  90. package/runtime/arcane/modules/Mail.js +738 -115
  91. package/runtime/arcane/modules/MailOutbox.mjs +1395 -0
  92. package/runtime/arcane/modules/MailTransport.mjs +197 -39
  93. package/runtime/arcane/modules/Ollama.js +36 -1
  94. package/runtime/arcane/modules/OpenMeteoWeatherProvider.js +583 -7
  95. package/runtime/arcane/modules/PreferenceStore.js +367 -33
  96. package/runtime/arcane/modules/RecordReviewStore.js +322 -23
  97. package/runtime/arcane/modules/ScreenCapture.js +1397 -15
  98. package/runtime/arcane/modules/SpeechPlayback.js +438 -41
  99. package/runtime/arcane/modules/TerminalClient.js +277 -12
  100. package/runtime/arcane/modules/ThemeBootstrap.js +80 -6
  101. package/runtime/arcane/modules/ThemeManager.js +39 -7
  102. package/runtime/arcane/modules/TimeGuard.js +131 -20
  103. package/runtime/arcane/modules/WaitForComponent.js +386 -33
  104. package/schemas/arcane-lock.schema.json +2 -2
  105. package/src/cli/main.mjs +435 -9
  106. package/src/event-manager.mjs +1097 -1
  107. package/src/import-map.mjs +21 -3
  108. package/src/index.mjs +13 -0
  109. package/src/installed-sdk-runtime.mjs +112 -0
  110. package/src/mail-api.mjs +22 -0
  111. package/src/mail-credentials.mjs +667 -0
  112. package/src/mail-server.mjs +1769 -0
  113. package/src/mail.mjs +261 -0
  114. package/src/sdk-browser-runtime.mjs +85 -41
  115. package/src/testing-loader.mjs +7 -0
  116. package/src/toolchain.mjs +3 -0
  117. package/src/workspace.mjs +1 -1
@@ -9,7 +9,7 @@ page is the focused local-browser path beneath the normalized AI decision
9
9
  guide.
10
10
 
11
11
  The wiring example assumes a scaffolded or materialized Arcane application
12
- with SDK `0.2.1`'s authenticated runtime tree and generated browser import map.
12
+ with SDK `0.3.0`'s runtime tree and generated browser import map.
13
13
  `arcane/DBOPFS` is a managed browser-map specifier, not an npm package export.
14
14
  See [browser runtime delivery](../protocols.md#browser-runtime-delivery) before
15
15
  using the example in a custom host or bundler.
@@ -128,8 +128,9 @@ default for its check.
128
128
  An enabled byte-length check requires descriptor `bytes` and compares it with
129
129
  the actual cached or downloaded byte count. A disabled byte-length check permits
130
130
  `bytes` to be absent and never rejects a cached or downloaded model by comparing
131
- it with an expected size. The store still counts and records the observed byte
132
- length for storage and progress metadata on every install and cache reuse.
131
+ it with an expected size. The store still counts and records the
132
+ observed byte length for storage and progress metadata on every install and
133
+ cache reuse.
133
134
 
134
135
  An enabled SHA-256 check requires descriptor `sha256` and hashes the actual
135
136
  stored or cached file. A disabled SHA-256 check permits `sha256` to be absent
@@ -158,8 +159,8 @@ console.log(integrity.byteLength.observed); // actual cached/downloaded bytes
158
159
  For one-file compatibility, older descriptors can supply `immutableUrl` as the
159
160
  URL alias and `name` as a cache-filename hint. If both `url` and
160
161
  `immutableUrl` are present, they must match. Legacy `licenseSpdx` and
161
- `sourceRevision` properties are not canonical descriptor fields or runtime
162
- admission checks; applications remain responsible for model selection,
162
+ `sourceRevision` properties are
163
+ not canonical descriptor fields or runtime admission checks; applications remain responsible for model selection,
163
164
  provenance, and license compliance. Version-2/3 compatibility is internal; a
164
165
  new successful completion is always recorded as version 4 without inventing an
165
166
  integrity result.
@@ -316,8 +317,8 @@ The SDK default is `secure:false`; `ai.load({security})` can override inherited
316
317
  fields for that operation.
317
318
 
318
319
  When `llm` is an existing `ModelController`, that controller keeps the security
319
- and load policy with which it was created. This function does not reapply its
320
- `loadPolicy` argument in that case, and supplying `security` alongside the
320
+ and load policy with which it was created. This function
321
+ does not reapply its `loadPolicy` argument in that case, and supplying `security` alongside the
321
322
  existing controller throws `TypeError`. Passing a provider instead creates a
322
323
  new controller with the requested policy and security.
323
324
 
@@ -490,6 +491,16 @@ localOnly:true,catalog,inspect,status,load,request,unload,dispose}`. Inspection
490
491
  returns `arcane-ai-model-authority/1` only for an exact catalog selection.
491
492
  `request()` admits only `chat` and `stream` and preserves structural tool data.
492
493
 
494
+ ### Availability and normalization
495
+
496
+ The adapter is available anywhere the caller can supply an admitted
497
+ `arcane-ai-browser-wasm/1` provider object. It performs only the versioned
498
+ provider-shape normalization into `arcane-ai-provider/2`; it does not create a
499
+ runtime, choose or download a model, grant host capability, change local-only
500
+ behavior, or make an arbitrary provider authoritative. Provider lifecycle,
501
+ cancellation, catalog selection, and failures remain owned by the wrapped
502
+ provider and are forwarded through the normalized role contract.
503
+
493
504
  ### Example
494
505
 
495
506
  ```javascript
@@ -91,7 +91,7 @@ surface does not require an Arcane Core method grant because it does not call a
91
91
  Core host. Browser Fetch, CORS, storage policy, secure-context behavior, and
92
92
  resource limits still apply.
93
93
 
94
- The shipped `0.2.1` runtime requires WebGPU and has no CPU fallback. A successful
94
+ The shipped `0.3.0` runtime requires WebGPU and has no CPU fallback. A successful
95
95
  load requests full GPU offload (`gpuLayers: 99999`) and admits actual adapter,
96
96
  full-offload, buffer, queue, and settled-fence evidence. `navigator.gpu`
97
97
  presence by itself is not readiness. The provider emits the instrumented
@@ -128,8 +128,11 @@ through an SDK-created authority and DBOPFS artifact store.
128
128
 
129
129
  The projected [`AIProviderRuntime`](runtime-modules.md#aiproviderruntimejs)
130
130
  normalizes those browser providers and can admit an externally supplied native
131
- or cloud provider/2 adapter. SDK `0.2.1` does not publish a native, Core, or
132
- cloud provider/2 adapter. The sticky
131
+ or cloud provider/2 adapter. `AI.js` also supplies compatibility adapters for
132
+ an already-selected legacy OpenAI route, Ollama route, or admitted Core speech
133
+ route. SDK `0.3.0` publishes no privileged Core implementation, credential,
134
+ model, or speech-runtime authority, and those adapters never probe, select,
135
+ download, or fall back. The sticky
133
136
  [`AIRuntimeState`](runtime-modules.md#airuntimestatejs) surface keeps
134
137
  application UI independent of transport. A selected route remains explicit:
135
138
  browser failure is not permission to invoke Core or cloud.
@@ -34,12 +34,12 @@ release acceptance.
34
34
  | Surface | Minimum behavior proved locally | Heavier evidence boundary |
35
35
  | --- | --- | --- |
36
36
  | Package entrypoints | Every declared JavaScript export imports; documented names match; constants and synchronous validators preserve their public contracts. | None for import itself. Operations that invoke tools use the matching boundary below. |
37
- | EventManager and event stacks | Live pub/sub ordering and payload identity, nested causation, immutable/redacted snapshots, strict import, bounded overflow, seek, all playback modes/lifecycle outcomes, cancellation, and DOM start/stop/privacy behavior. | Real user journeys and browser layout belong in a browser harness; event-stack review never proves that external side effects can be replayed. |
37
+ | Canonical events, EventManager, and event stacks | One branded/versioned `globalThis.arcaneEvents` per realm, fail-closed collision admission, duplicate-module reuse, declared source ownership, canonical/source delivery order, frozen occurrence metadata, exact cancellation, AbortSignal cleanup, disposable subscriptions, source teardown/re-registration, observational listener failure, EventTarget compatibility, one-way DOM projection, deprecated state-free `aiRuntimeEvents`, live isolated-bus pub/sub, nested causation, immutable/redacted stacks, strict import, bounded overflow, seek, playback, and DOM privacy/lifecycle. | Real user journeys and browser layout belong in a browser harness; an occurrence, EventTarget/DOM projection, or event-stack review never proves that external side effects stopped, completed, or can be replayed. |
38
38
  | CLI | Commands parse, acknowledge, select one scope, produce normalized human/JSON/NDJSON output, propagate cancellation/failure, and reject invalid cardinality. | Native build/run requires the selected real provider and host. |
39
39
  | Browser runtime modules | Every shipped ESM module parses and its export inventory matches the catalog; pure helpers run focused success/error cases. | DOM, OPFS, media, and Web Component journeys use a browser harness. |
40
- | Provider-neutral AI runtime and chat/speech activation | Provider/2 registration, closed three-role configuration, opt-in STT startup, legacy Cloud/Core speech readiness, independent LLM/STT/TTS load/unload/status, latest-request-wins settlement, owned STT signals, TTS mute lifecycle, route-owned voice defaults, sticky-state-only speech readiness, selected-unloaded activation request/cancellation/error events, stale-callback suppression, and absence of silent provider fallback are exercised against bounded providers and host callbacks. | Real model/runtime admission remains the selected provider's evidence boundary; provider-promise settlement, state, an abort signal, or an activation event does not by itself prove underlying provider work stopped or native, cloud, or browser-model availability. |
41
- | Browser-WASM local AI | The exact exported namespace, canonical ordered `{id, files:[{name?,url,bytes?,sha256?},...]}` descriptor plus its one-file compatibility input, fieldwise app/provider/load security precedence, default-unchecked and secure-check paths, observed-byte persistence, honest capability/status reasons, provider/facade lifecycle, lazy/manual policy, successful Wllama-load requirement, abort normalization, and structural-only tool behavior run with bounded deterministic providers. | The publication gate installs the packed SDK into a real Chrome app, loads the authenticated Wllama 3.6.0 JS/WASM assets, configures `secure:true`, performs a cold exact-length/SHA-256 model install, real inference, in-flight cancellation, unload, and a verified offline reload with zero model requests. It is an explicit heavyweight capability gate, not an implicit model download in every local `npm run check`. |
42
- | Browser speech | Caller-owned Whisper/Kokoro authority, closed runtime graph, app/provider/load security precedence, manifest-last DBOPFS cache, strict offline admission, independent Worker lifecycle, pre-Worker versus in-Worker cancellation, Blob/File STT conversion, WAV TTS conversion, and no cloud fallback are exercised with bounded synthetic artifacts and adapters. | A real runtime/model/voice download and actual transcription or synthesis require the application's admitted immutable artifacts, licenses, browser media support, and explicit user action. |
40
+ | Provider-neutral AI runtime and chat/speech activation | Provider/2 registration, closed three-role configuration, opt-in STT startup, legacy Cloud/Core speech readiness, independent LLM/STT/TTS load/unload/status, latest-request-wins settlement, owned STT signals, TTS mute lifecycle, route-owned voice defaults, sticky-state-only readiness for both speech components, shared selected-unloaded activation request/cancellation/error behavior, fail-closed programmatic voice recording, public transcript-replacement supersession of late transcribe/save/complete settlement, `AI.fetchSTT` callback-position compatibility, stale-callback suppression, and absence of silent provider fallback are exercised against bounded providers and host callbacks. | Real model/runtime admission remains the selected provider's evidence boundary; provider-promise settlement, state, an abort signal, or an activation event does not by itself prove underlying provider work stopped or native, cloud, or browser-model availability. |
41
+ | Browser-WASM local AI | The exact exported namespace, canonical ordered `{id, files:[{name?,url,bytes?,sha256?},...]}` descriptor plus its one-file compatibility input, fieldwise app/provider/load security precedence, default-unchecked and secure-check paths, observed-byte persistence, honest capability/status reasons, provider/facade lifecycle, lazy/manual policy, successful Wllama-load requirement, abort normalization, and structural-only tool behavior run with bounded deterministic providers. | An optional explicit `secure:true` verification may install the packed SDK into a real Chrome app, load authenticated Wllama 3.6.0 JS/WASM assets, perform a cold exact-length/SHA-256 model install, real inference, in-flight cancellation, unload, and verified offline reuse. That heavyweight hardening proof is not an ordinary publication gate or an implicit model download. |
42
+ | Browser speech | Caller-owned Whisper/Kokoro authority, independent STT/TTS routes, ordinary direct upstream runtime/model authority, explicit `secure:true` graph admission, manifest-last DBOPFS cache, strict offline admission, independent Worker lifecycle, pre-Worker versus in-Worker cancellation, Blob/File STT conversion, WAV TTS conversion, and no cloud fallback are exercised with bounded synthetic artifacts and adapters. | A real runtime/model/voice download and actual transcription or synthesis use the application's selected upstream packages/providers, browser media support, and explicit user action. Optional strict graph evidence remains scoped to `secure:true`. |
43
43
  | Persistent chat and document context | Atomic in-memory/history commit, explicit per-turn persistence, single structural tool-call sequencing, bounded bootstrap/search/context, caller-source `evaluate()` budgets, cancellation, and reject versus `preserve-readable` partial coverage are exercised with app-scoped adapters. | Live Core/provider inference and durable browser storage remain separate authorities; tests never treat a fake chat function or in-memory adapter as host/storage proof. |
44
44
  | Core bridge docs | Canonical namespace/method/event/entity inventories match their one-per-member guides and required sections. | Live Core conformance belongs in Arcane OS because Core implementation is not shipped as SDK source. |
45
45
  | Arcane Ollama wrapper | Missing-host error, method forwarding, text/readiness normalization, unload request, and stream-option forwarding run against a deterministic fake `Arcane.ollama`. | Real managed-service, model download/create, GPU/resource admission, and service restart require an admitted Arcane host. |
@@ -100,10 +100,33 @@ continued unrecorded live delivery, rejection when re-enabling before
100
100
  DOM cases assert that private values, credentials, sensitive attributes, URLs,
101
101
  and markup remain redacted under every capture-option combination.
102
102
 
103
+ The focused singleton contract also owns these cases in
104
+ `test/event-manager.test.mjs`: global property/brand/protocol/API descriptor
105
+ admission; same-object reuse across duplicate module URLs and package
106
+ entrypoints; exact `subscribe(type,handler,{once,signal})` behavior; idempotent
107
+ `unsubscribe()`/`unsubscribe.dispose()`; one active
108
+ `createSource(owner,{source,eventTypes,onListenerError})` handle; immutable
109
+ `arcane-event-occurrence/1` values and privacy separation; synchronous
110
+ cancellation; dispatch-safe removal and reentry; final source disposal;
111
+ EventTarget deduplication/admission; one-way `CustomEvent` projection; and
112
+ nonrecursive listener-error publication. Runtime behavior tests own the
113
+ `aiRuntimeEvents` compatibility view and each migrated module/component's
114
+ instance-scoped projection and cleanup. Reference-completeness tests own the
115
+ public export names and exact focused-guide coverage.
116
+
117
+ Canonical event publication itself is deliberately synchronous and
118
+ observational. Tests must not await listener return values or present
119
+ `arcaneEvents` as backpressure. Promise settlement, async callback failure, and
120
+ ordered delivery belong to the operation promise or `createEventQueue()` test
121
+ that owns that work. Abort-driven listener removal proves cleanup only; it does
122
+ not prove already-started host, provider, worker, or queue work stopped.
123
+
103
124
  ## Test ownership
104
125
 
105
- The SDK owns package, CLI, synchronized renderer, documentation, and injected
106
- provider-boundary behavior. Arcane OS owns live Core dispatch, native host
126
+ The SDK owns the singleton authority, its per-realm source adapters, package and
127
+ managed-browser projections, focused event/source/DOM contracts, runtime
128
+ compatibility views, package, CLI, synchronized renderer, documentation, and
129
+ injected provider-boundary behavior. Arcane OS owns live Core dispatch, native host
107
130
  bridges, capability policy, host service adapters, and real ArcaneOllama
108
131
  integration. A change that crosses both repositories needs focused tests at both
109
132
  owners; copying a Core test into this package would not make the SDK the Core
@@ -31,6 +31,9 @@ and exits nonzero on failure. Machine output is defined by
31
31
  | `arcane update-check` | Performs one explicit, read-only npm dist-tag query for the installed SDK version. |
32
32
  | `arcane targets` | Lists target ids, declared status, formats, architectures, signing profiles, methods, and pairing reason. |
33
33
  | `arcane repo status\|pull\|push` | Runs one selected repository operation for the current app workspace. |
34
+ | `arcane mail key set\|status\|delete` | Manages one server-only Resend API-key profile in Windows Credential Manager. |
35
+ | `arcane mail send` | Performs one explicit, idempotency-keyed Resend attempt from a bounded JSON report on redirected stdin. |
36
+ | `arcane mail serve` | Starts one authenticated numeric-loopback Arcane-to-Resend gateway with exact app, Origin, and recipient admission. |
34
37
 
35
38
  ## Parser-wide options
36
39
 
@@ -42,21 +45,30 @@ meaning and cardinality rules:
42
45
  | `--path` | directory | `new` |
43
46
  | `--display-name` | string | `new`, `init` |
44
47
  | `--workspace` | directory | Commands that select an external or integrated workspace; defaults to `.`. |
45
- | `--app` | app id | Workspace/app operations except shared scope and `verify-bundle`. |
48
+ | `--app` | app id | Workspace/app operations except shared scope and `verify-bundle`; also the exact `mail serve` caller id. |
46
49
  | `--arcane-root` | directory | `doctor`, native `build`/`run`, `native-doctor`, `native-prepare` |
47
- | `--host` / `--port` | host / integer 0–65535 | Browser `dev` and `run`; defaults to `127.0.0.1:8000`. |
50
+ | `--host` / `--port` | host / integer 0–65535 | Browser `dev`/`run` default to `127.0.0.1:8000`; `mail serve` defaults to `127.0.0.1:8025` and admits numeric loopback only. |
48
51
  | `--target` | target id | `new`, `init`, native diagnostics, `build`, `run` |
49
52
  | `--format` / `--signing` | target-supported values | Native diagnostics, `build`, `run` |
50
53
  | `--output-root` | directory | Native `build` and `run` |
51
54
  | `--scope` | `app` or `shared` | `test`, `check`; defaults to `app`. |
52
55
  | `--test-file` | repository-relative `.test.mjs` | `test --scope shared` only |
53
56
  | `--artifact` | bundle path | `bundle`, `verify-bundle` |
57
+ | `--profile` | credential profile id | `mail send`, `mail serve` |
58
+ | `--from` | verified sender | `mail send`, `mail serve` |
59
+ | `--origin` | exact browser origin | `mail serve` |
60
+ | `--allow-to` | one to 50 comma-separated addresses | `mail serve` |
61
+ | `--report-key` | 8–128 safe characters | `mail send`; caller-owned stable Resend idempotency key |
62
+ | `--request-timeout` | integer 1000–600000 ms | `mail send`, `mail serve` |
54
63
  | `--output` | `human`, `json`, `ndjson` | Every invocation; the final occurrence wins. |
55
64
  | `--git` | flag | `new` |
56
65
  | `--skip-tests` | flag | `check --scope app` |
57
66
  | `--dry-run` | flag | `package`; parser-supported on `build` with the boundary below |
58
67
  | `--require-local-ai` | flag | `doctor` |
59
68
  | `--overwrite` | flag | `bundle` only |
69
+ | `--secret-stdin` | flag | `mail key set`; requires redirected input |
70
+ | `--app-key-stdin` | flag | `mail serve`; requires redirected input |
71
+ | `--report-stdin` | flag | `mail send`; requires redirected JSON input |
60
72
  | `--help`, `-h` | flag | Prints help and exits zero. |
61
73
  | `--version`, `-v` | flag | Prints the exact SDK version and exits zero. |
62
74
 
@@ -185,10 +197,11 @@ identical executable alias.
185
197
  The generated artifact is
186
198
  `apps/<id>/modules/arcane.importmap.json`. Its exact JSON is also installed in
187
199
  the app entry as `<script type="importmap" data-arcane-import-map>` before
188
- module loading. In SDK `0.2.1`, the complete authenticated physical-v1 runtime
189
- produces 91 entries and intentionally has no package-root mapping. That count
190
- describes the shipped SDK closure; the command receipt remains authoritative
191
- for the exact map written to the selected application.
200
+ module loading. In SDK `0.3.0`, the complete physical-v1 runtime derives its
201
+ entries from the installed runtime and browser-runtime inventories and
202
+ intentionally has no package-root mapping. The command receipt remains
203
+ authoritative for the exact map written to the selected application; no fixed
204
+ entry count is a release contract.
192
205
 
193
206
  ### Result and safety
194
207
 
@@ -207,7 +220,7 @@ Success returns the normal selected-workspace wrapper:
207
220
  documentPaths,
208
221
  documentCount:1,
209
222
  imports,
210
- entryCount:91,
223
+ entryCount:Object.keys(imports).length,
211
224
  excludedModules:['modules/CaseEvidenceIndexer.js'],
212
225
  files:[
213
226
  {role:'artifact',path,bytes,sha256},
@@ -573,8 +586,8 @@ Success returns:
573
586
  ```javascript
574
587
  {
575
588
  packageName:'arcane-os',
576
- currentVersion:'0.2.0',
577
- registryVersion:'0.2.1',
589
+ currentVersion:'0.2.1',
590
+ registryVersion:'0.2.2',
578
591
  tag:'latest',
579
592
  status:'update-available', // or 'current' or 'ahead'
580
593
  updateAvailable:true,
@@ -648,6 +661,101 @@ loop across workspaces.
648
661
  npm exec -- arcane repo status
649
662
  ```
650
663
 
664
+ ## `arcane mail`
665
+
666
+ ### Resend credential profiles
667
+
668
+ The credential subcommands select one local profile:
669
+
670
+ ```text
671
+ arcane mail key set <profile> [--secret-stdin]
672
+ arcane mail key status <profile>
673
+ arcane mail key delete <profile>
674
+ ```
675
+
676
+ `key set` reads the Resend API key from a hidden terminal prompt. The
677
+ `--secret-stdin` form is for deliberately redirected non-interactive input and
678
+ rejects a TTY before reading. The key is sent to the Windows Credential Manager
679
+ helper over child-process stdin, never argv, and no plaintext fallback is
680
+ created. Status reports only whether the profile exists. Delete returns the
681
+ selected profile with `exists:false`; it intentionally does not distinguish a
682
+ new deletion from an already-absent profile. Non-Windows hosts fail closed.
683
+
684
+ Machine output for `key set` requires `--secret-stdin`. Raw CLI arguments are
685
+ not included in acceptance events, and usage errors do not echo unknown option
686
+ or positional values.
687
+
688
+ ### One-shot provider send
689
+
690
+ `mail send` performs exactly one Resend provider attempt without starting a
691
+ loopback server:
692
+
693
+ ```text
694
+ arcane mail send --profile <profile> --from <verified-sender> --report-key <id> --report-stdin [--request-timeout <ms>]
695
+ ```
696
+
697
+ `--report-stdin` is mandatory and rejects a terminal before attaching input
698
+ listeners. It accepts one UTF-8 JSON object up to 52 MiB using the existing
699
+ gateway report shape:
700
+
701
+ ```json
702
+ {
703
+ "type": "report",
704
+ "to": ["recipient@example.com"],
705
+ "subject": "Example",
706
+ "text": "Message content"
707
+ }
708
+ ```
709
+
710
+ The exact closed report keys are `type`, `to`, `subject`, and at least one of
711
+ `text` or `html`. Direct CLI sending requires one to 50 explicit unique
712
+ recipients, including for `error` reports. The Resend credential comes only
713
+ from the selected Windows Credential Manager profile; neither it nor report
714
+ content is accepted through argv, environment variables, or result fields.
715
+
716
+ The caller owns `--report-key`. It must contain 8–128 ASCII letters, digits,
717
+ periods, underscores, colons, or hyphens. Reuse the same key only with the same
718
+ byte-equivalent logical report when deliberately reconciling or retrying an
719
+ ambiguous attempt. The CLI never retries automatically.
720
+
721
+ Exit zero means Resend returned a successful response with a valid provider
722
+ acceptance id. The privacy-safe result contains only provider, status,
723
+ classification, request id, provider id, provider HTTP status, and recipient
724
+ count. It proves provider API acceptance, not inbox delivery. Permanent,
725
+ retryable, and ambiguous outcomes exit nonzero with only normalized code,
726
+ status, retry, uncertainty, and count metadata. Cancellation before the
727
+ provider attempt exits 130 without sending; cancellation, timeout, or transport
728
+ loss after the attempt begins is ambiguous because Resend may have accepted it.
729
+
730
+ ### Authenticated local gateway
731
+
732
+ `mail serve` starts one owned Node HTTP gateway:
733
+
734
+ ```text
735
+ arcane mail serve --profile <profile> --from <verified-sender> --app <id> --origin <exact-origin> --allow-to <addresses> [--app-key-stdin] [--host 127.0.0.1] [--port 8025] [--request-timeout <ms>]
736
+ ```
737
+
738
+ The selected credential profile supplies only the server-side Resend API key.
739
+ A separate local mail app key is read through a hidden prompt. Structured
740
+ output requires `--app-key-stdin` with redirected input; the app key is never an
741
+ argv value or part of the server result. The browser must use the same value as
742
+ `arcane.config.mail.appKey`.
743
+
744
+ The CLI admits only numeric loopback host values accepted by the gateway. The
745
+ gateway also binds the exact app id, Origin, sender, and recipient allowlist,
746
+ and it requires the separate app key by default. `--allow-to` accepts one to 50
747
+ comma-separated unique recipients. `--request-timeout` is the one provider
748
+ attempt timeout in milliseconds and defaults to `30000`.
749
+
750
+ After binding, `server.ready` reports only sanitized lifecycle fields such as
751
+ protocol, app id, loopback address, port, URL, and caller-authentication mode.
752
+ The command owns the server until its lifecycle ends or `SIGINT`/`SIGTERM`
753
+ cancels it. Neither Resend nor local app credentials, sender/recipient policy,
754
+ or message content appear in the result or observer events.
755
+
756
+ See [Mail gateway and durable outbox](mail.md) for request, retry,
757
+ idempotency, DBOPFS, and provider-acceptance semantics.
758
+
651
759
  ## Machine output
652
760
 
653
761
  `--output json` returns one complete JSON document after structured progress is
@@ -9,7 +9,7 @@ They are not TypeScript declarations.
9
9
 
10
10
  ## Portable SDK AI and Core AI
11
11
 
12
- The SDK `0.2.1` has two related but separate normalized boundaries:
12
+ The SDK `0.3.0` has two related but separate normalized boundaries:
13
13
 
14
14
  | Boundary | Use | Host |
15
15
  |---|---|---|