arcane-os 0.2.1 → 0.2.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 (30) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +8 -8
  3. package/browser-runtime/ARCANE_SDK_BROWSER_RELEASE.json +5 -5
  4. package/browser-runtime/ai/browser-speech-providers.mjs +1 -0
  5. package/docs/architecture.md +2 -2
  6. package/docs/reference/README.md +79 -13
  7. package/docs/reference/ai/browser-speech.md +336 -0
  8. package/docs/reference/ai/browser-wasm.md +207 -82
  9. package/docs/reference/availability-and-normalization.md +33 -4
  10. package/docs/reference/behavioral-testing.md +4 -1
  11. package/docs/reference/cli.md +29 -10
  12. package/docs/reference/core/arcane-ai-contracts.md +43 -9
  13. package/docs/reference/inventory/package-api.json +110 -14
  14. package/docs/reference/inventory/runtime-components.json +42 -14
  15. package/docs/reference/inventory/runtime-modules.json +118 -13
  16. package/docs/reference/protocols.md +264 -38
  17. package/docs/reference/runtime-components.md +177 -21
  18. package/docs/reference/runtime-modules.md +449 -13
  19. package/docs/reference/sdk-api.md +626 -85
  20. package/package.json +1 -1
  21. package/runtime/ARCANE_RUNTIME_RELEASE.json +19 -19
  22. package/runtime/arcane/components/chat.html +17 -52
  23. package/runtime/arcane/components/speech.html +109 -29
  24. package/runtime/arcane/components/voice-transcription.html +437 -68
  25. package/runtime/arcane/modules/AI.js +556 -128
  26. package/runtime/arcane/modules/AIProviderRuntime.js +299 -30
  27. package/runtime/arcane/modules/AIRuntimeState.js +23 -4
  28. package/runtime/arcane/modules/ComponentContracts.js +272 -0
  29. package/runtime/arcane/modules/LocalAIReadinessController.js +1 -1
  30. package/schemas/arcane-lock.schema.json +2 -2
@@ -29,7 +29,7 @@ A component file does not register its own custom element. The `<html-import>` h
29
29
  | [`assistant-panel.html`](#assistant-panelhtml) | Reusable assistant drawer, message area, composer, pending/streaming/empty/error state, and actions. | `open()`<br>`close()`<br>`toggle()`<br>`send()`<br>`clear()`<br>`setState()`<br>`focusComposer()`<br>`scrollToEnd()` | `assistant-ready`<br>`assistant-send`<br>`assistant-clear` | DOM-normalized; caller/provider results remain external |
30
30
  | [`calculator.html`](#calculatorhtml) | Calculator keypad and result/error event surface backed by CalculatorEngine. | `calculate()` | `calculator-ready`<br>`calculation-complete`<br>`calculation-error` | Normalized Calculation/error events |
31
31
  | [`chart.html`](#charthtml) | Accessible uPlot line, area, or point chart with normalized options and rows. | `configure()`<br>`populate()`<br>`setData()`<br>`addData()`<br>`update()`<br>`destroy()` | `chart-ready`<br>`chart-remove` | Options/rows normalized; uPlot rendering is vendor-native |
32
- | [`chat.html`](#chathtml) | Shared chat, file upload, streaming, speech, language, availability, and conversation-timebox surface. | `streamMessage()`<br>`setMessageProgress()`<br>`setAIAvailability()`<br>`setInitialSpeechMuted()`<br>`setConversationComplete()`<br>`bindConversationTimebox()`<br>`submitMessage()`<br>`sendMessage()`<br>`languageChanged()` | `chat-ready`<br>`chat-send-message`<br>`chat-send-error`<br>`chat-file-uploaded`<br>`chat-language-changed`<br>`conversation-timebox-error` | UI state normalized; AI/storage/media behavior mixed |
32
+ | [`chat.html`](#chathtml) | Shared chat, visible selected-model activation request, file upload, streaming, speech, language, availability, and conversation-timebox surface. | `streamMessage()`<br>`setMessageProgress()`<br>`setAIAvailability()`<br>`setInitialSpeechMuted()`<br>`setConversationComplete()`<br>`bindConversationTimebox()`<br>`submitMessage()`<br>`sendMessage()`<br>`languageChanged()`<br>`requestAIActivation()`<br>`destroy()` | `chat-ready`<br>`chat-send-message`<br>`chat-send-error`<br>`chat-file-uploaded`<br>`chat-language-changed`<br>`chat-ai-activation-request`<br>`chat-ai-activation-error`<br>`conversation-timebox-error` | UI/runtime state and explicit user activation intent normalized; AI/storage/media behavior mixed |
33
33
  | [`conversation-view.html`](#conversation-viewhtml) | Provider-neutral conversation display, advisory actions, composer, busy state, and status. | `setConversation()`<br>`setBusy()`<br>`setStatus()`<br>`clearComposer()` | `conversation-view-ready`<br>`communication-send`<br>`communication-advisory-action` | DOM-normalized |
34
34
  | [`dashboard-config.html`](#dashboard-confightml) | Selects which normalized chart definitions are visible on a dashboard. | `configure()`<br>`setDefinitions()`<br>`setVisibility()`<br>`getChartOptions()`<br>`getEffectiveVisibility()`<br>`open()`<br>`close()` | `dashboard-config-ready`<br>`dashboard-config-opened`<br>`dashboard-config-closed`<br>`dashboard-config-change` | Fully normalized definitions and visibility |
35
35
  | [`data-maintenance.html`](#data-maintenancehtml) | Runs destructive cleanup of empty chats and memories inside the current app data scope. | `open()` | `data-maintenance-ready`<br>`data-maintenance-complete` | Normalized counts; DBOPFS failures mixed |
@@ -53,7 +53,7 @@ A component file does not register its own custom element. The `<html-import>` h
53
53
  | [`screen-capture.html`](#screen-capturehtml) | Presents image, video, or GIF display-capture workflow. | `capture()` | `screen-capture-ready`<br>`screen-capture-result` | State/result normalized; media permission/codec failures mixed |
54
54
  | [`source-code-viewer.html`](#source-code-viewerhtml) | Renders line-addressable source code with load, error, focus, and state behavior. | `configure()`<br>`load()`<br>`render()`<br>`clear()`<br>`fail()`<br>`focus()`<br>`focusLine()` | `source-code-viewer-ready`<br>`source-code-viewer-state` | Normalized source/state |
55
55
  | [`source-explanation.html`](#source-explanationhtml) | Presents an evidence finding, source selection, explanation, and save state. | `showFinding()`<br>`populate()`<br>`selectSource()`<br>`markSaved()` | `source-explanation-ready`<br>`source-explanation-save`<br>`source-explanation-source-selected` | DOM-normalized |
56
- | [`speech.html`](#speechhtml) | Coordinates speech controls, transcription completion, mute state, and microphone availability. | `configure()`<br>`setAvailability()`<br>`setMuted(); availability`<br>`muted`<br>`initialMuted`<br>`componentReady properties` | `speech-ready`<br>`speech-transcription-complete`<br>`speech-microphone-unavailable` | UI state normalized; AI/media behavior mixed |
56
+ | [`speech.html`](#speechhtml) | Coordinates explicit STT activation, speech controls, transcription completion, mute state, and microphone availability. | `configure()`<br>`setAvailability()`<br>`setMuted()`<br>`requestSTTActivation()`<br>`destroy()`<br>`availability`<br>`muted`<br>`initialMuted`<br>`componentReady` | `speech-ready`<br>`speech-transcription-complete`<br>`speech-transcription-error`<br>`speech-transcription-cancelled`<br>`speech-microphone-unavailable`<br>`speech-stt-activation-request`<br>`speech-stt-activation-error`<br>`speech-tts-lifecycle-error` | Sticky runtime speech readiness, explicit STT activation, request cancellation, and TTS mute lifecycle intent normalized; provider/model authority and media behavior remain external |
57
57
  | [`summary-strip.html`](#summary-striphtml) | Displays compact selectable KPI or summary items. | `configure()`<br>`setItems()`<br>`updateItem()`<br>`clear()` | `summary-strip-ready`<br>`summary-strip-change`<br>`summary-strip-select` | DOM-normalized |
58
58
  | [`table.html`](#tablehtml) | Builds and updates a simple header/body table. | `buildHeader()`<br>`buildTable()` | `table-ready`<br>`header-update`<br>`body-update` | DOM-normalized |
59
59
  | [`task-progress.html`](#task-progresshtml) | Runs and displays a task list with started/change/complete/error state. | `configure()`<br>`setTasks()`<br>`updateTask()`<br>`runTasks()`<br>`clear()` | `task-progress-ready`<br>`task-progress-started`<br>`task-progress-change`<br>`task-progress-complete`<br>`task-progress-error` | Task state normalized; injected task results mixed |
@@ -61,7 +61,7 @@ A component file does not register its own custom element. The `<html-import>` h
61
61
  | [`theme-editor.html`](#theme-editorhtml) | Edits, previews, saves, and resets semantic custom theme tokens. | `configure()`<br>`getTheme()`<br>`setTheme()`<br>`setBusy()`<br>`setStatus()` | `theme-editor-ready`<br>`theme-preview`<br>`theme-save`<br>`theme-reset` | Fully normalized Theme values |
62
62
  | [`theme-switcher.html`](#theme-switcherhtml) | Selects and refreshes system, light, dark, or custom theme mode. | `setMode()`<br>`refresh()` | No component-specific event | Preference/native appearance behavior mixed; no component-ready contract |
63
63
  | [`unified-inbox.html`](#unified-inboxhtml) | Displays provider-neutral communication threads with active/loading state. | `configure()`<br>`setThreads()`<br>`setActive()`<br>`setLoading()` | `unified-inbox-ready`<br>`inbox-refresh`<br>`thread-select` | DOM-normalized |
64
- | [`voice-transcription.html`](#voice-transcriptionhtml) | Records segmented microphone audio, transcribes, persists, and completes a combined transcript. | `configure()`<br>`startRecording()`<br>`stopRecording()`<br>`save()`<br>`completeTranscription()/complete()`<br>`clear()`<br>`reset()`<br>`destroy()` | `voice-transcription-ready`<br>`voice-transcription-state`<br>`voice-transcription-segment`<br>`voice-transcription-change`<br>`voice-transcription-complete`<br>`speech-transcription-complete` | State/text normalized; media/provider behavior mixed |
64
+ | [`voice-transcription.html`](#voice-transcriptionhtml) | Records segmented microphone audio only after authoritative STT admission, exposes explicit selected-STT activation, transcribes with cancellation, persists, and completes a combined transcript. | `configure()`<br>`requestSTTActivation()`<br>`startRecording()`<br>`stopRecording()`<br>`save()`<br>`completeTranscription()/complete()`<br>`clear()`<br>`reset()`<br>`destroy()` | `voice-transcription-ready`<br>`voice-transcription-state`<br>`voice-transcription-segment`<br>`voice-transcription-change`<br>`voice-transcription-complete`<br>`speech-transcription-complete`<br>`speech-transcription-cancelled`<br>`speech-stt-activation-request`<br>`speech-stt-activation-error` | Sticky runtime STT readiness, explicit activation, request cancellation, and state/text are normalized; media/provider behavior remains external |
65
65
  | [`weather-widget.html`](#weather-widgethtml) | Displays normalized current and daily weather with refresh intent. | `setWeather()`<br>`clear()` | `weather-widget-ready`<br>`weather-refresh` | Display normalized; provider supplied externally |
66
66
  | [`web-navigator.html`](#web-navigatorhtml) | Guards embedded/external navigation and surfaces allow/block/open intents. | `configure()`<br>`navigate()`<br>`currentUrl()` | `web-navigator-ready`<br>`web-navigate`<br>`web-navigation-blocked`<br>`web-open-external` | Navigation intent/decision normalized; browser navigation result platform-native |
67
67
 
@@ -177,24 +177,63 @@ Shared dependencies: [`ChartLibrary.js`](runtime-modules.md#chartlibraryjs), [`C
177
177
 
178
178
  ### Overview
179
179
 
180
- Shared chat, file upload, streaming, speech, language, availability, and conversation-timebox surface.
180
+ Shared chat, visible selected-model activation request, file upload, streaming,
181
+ speech, language, availability, and conversation-timebox surface.
181
182
 
182
183
  ### Public surface
183
184
 
184
- Methods/properties: `streamMessage()`, `setMessageProgress()`, `setAIAvailability()`, `setInitialSpeechMuted()`, `setConversationComplete()`, `bindConversationTimebox()`, `submitMessage()`, `sendMessage()`, `languageChanged()`.
185
+ Methods/properties: `streamMessage()`, `setMessageProgress()`,
186
+ `setAIAvailability()`, `setInitialSpeechMuted()`,
187
+ `setConversationComplete()`, `bindConversationTimebox()`, `submitMessage()`,
188
+ `sendMessage()`, `languageChanged()`, `requestAIActivation()`, and `destroy()`.
185
189
 
186
190
  `sendMessage(text)` and `languageChanged(text)` are host-overridable async
187
191
  extension callbacks. The component installs warning-only defaults when the host
188
192
  does not supply them; applications may instead consume the corresponding
189
193
  `chat-send-message` and `chat-language-changed` events.
190
194
 
191
- Events: `chat-ready`, `chat-send-message`, `chat-send-error`, `chat-file-uploaded`, `chat-language-changed`, `conversation-timebox-error`.
192
-
193
- Shared dependencies: [`MD.js`](runtime-modules.md#mdjs), [`File.js`](runtime-entities.md#filejs), [`ConversationTimebox.js`](runtime-modules.md#conversationtimeboxjs).
195
+ `setAIAvailability()` remains an LLM compatibility input, but selected sticky
196
+ `AIRuntimeState` LLM state wins over that boolean. STT and TTS readiness always
197
+ comes from sticky runtime role state; the method never forwards compatibility
198
+ speech booleans or synthesizes ready speech roles without an admitted, loaded
199
+ provider.
200
+
201
+ When a selected LLM route is `unloaded` or in `error`, the component exposes a
202
+ keyboard-operable Start/Try again control while Send stays disabled. During
203
+ `loading`, the control becomes Cancel loading and reflects sticky progress.
204
+ The default `requestAIActivation(intent)` forwards frozen
205
+ `{role:'llm',action:'load'|'unload',reason:'user'}` to
206
+ `requestAIRuntimeIntent()`. A host may replace that callback.
207
+
208
+ Before the callback, the component dispatches the bubbles/composed/cancelable
209
+ `chat-ai-activation-request` event with frozen `{intent,state}` detail.
210
+ `preventDefault()` suppresses the callback. A callback failure dispatches the
211
+ bubbles/composed, noncancelable `chat-ai-activation-error` event with frozen
212
+ `{request,error,message}`. A recognized canceled load whose current route is
213
+ `unloaded` or `unloading` is not reported as an activation error.
214
+
215
+ `destroy()` aborts the component's AI-runtime-state subscription, destroys the
216
+ activation controller, removes its `pagehide` listener, calls the optional
217
+ speech controller's `destroy()`, sets `ready` to `false`, and returns
218
+ `undefined`. It does not initiate a provider load or unload.
219
+
220
+ Events: `chat-ready`, `chat-send-message`, `chat-send-error`,
221
+ `chat-file-uploaded`, `chat-language-changed`,
222
+ `chat-ai-activation-request`, `chat-ai-activation-error`, and
223
+ `conversation-timebox-error`.
224
+
225
+ Shared dependencies: [`MD.js`](runtime-modules.md#mdjs), [`File.js`](runtime-entities.md#filejs), [`ConversationTimebox.js`](runtime-modules.md#conversationtimeboxjs), [`AIRuntimeState.js`](runtime-modules.md#airuntimestatejs).
194
226
 
195
227
  ### Availability and normalization
196
228
 
197
- **Browser and supported native WebViews.** UI state normalized; AI/storage/media behavior mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. [Deep protocol details](protocols.md).
229
+ **Browser and supported native WebViews.** UI and provider-runtime state are
230
+ normalized; AI/storage/media behavior remains mixed. The component emits no
231
+ activation request on import or startup. After the user operates the visible
232
+ control and the component event is not canceled, it publishes a
233
+ capability-neutral user intent; a provider/runtime owner decides whether and
234
+ how to execute the requested load or unload. HTMLImport + DOM; injected
235
+ Arcane/provider modules where listed. Native methods remain subject to the
236
+ bound app's capabilities. [Deep protocol details](protocols.md).
198
237
 
199
238
  ### Example
200
239
 
@@ -812,19 +851,74 @@ Events: `source-explanation-ready`, `source-explanation-save`, `source-explanati
812
851
 
813
852
  ### Overview
814
853
 
815
- Coordinates speech controls, transcription completion, mute state, and microphone availability.
854
+ Coordinates explicit speech-to-text activation, speech controls, transcription
855
+ completion, mute state, and microphone availability.
816
856
 
817
857
  ### Public surface
818
858
 
819
- Methods/properties: `configure()`, `setAvailability()`, `setMuted(); availability`, `muted`, `initialMuted`, `componentReady properties`.
820
-
821
- Events: `speech-ready`, `speech-transcription-complete`, `speech-microphone-unavailable`.
822
-
823
- Shared dependencies: [`AI.js`](runtime-modules.md#aijs), [`DBLS.js`](runtime-modules.md#dblsjs).
859
+ Methods/properties: `configure()`, `setAvailability()`, `setMuted()`,
860
+ `requestSTTActivation()`, `destroy()`, `availability`, `muted`, `initialMuted`,
861
+ and `componentReady`.
862
+
863
+ Events: `speech-ready`, `speech-transcription-complete`,
864
+ `speech-transcription-error`, `speech-transcription-cancelled`,
865
+ `speech-microphone-unavailable`, `speech-stt-activation-request`,
866
+ `speech-stt-activation-error`, and `speech-tts-lifecycle-error`.
867
+
868
+ Shared dependencies: [`AI.js`](runtime-modules.md#aijs),
869
+ [`AIRuntimeState.js`](runtime-modules.md#airuntimestatejs),
870
+ [`ComponentContracts.js`](runtime-modules.md#componentcontractsjs), and
871
+ [`DBLS.js`](runtime-modules.md#dblsjs).
872
+
873
+ The Hold to talk control remains disabled unless sticky STT state is `ready`,
874
+ the role is not busy, and microphone capture is available. For an explicitly
875
+ selected STT route, a separate keyboard-operable control presents Start
876
+ transcription while `unloaded`, Cancel loading while `loading`, a disabled
877
+ Canceling state while `unloading`, and Try again with the sticky error while
878
+ `error`. Selected-unloaded, busy, and error states are shown as distinct facts;
879
+ none is treated as ready.
880
+
881
+ The default `requestSTTActivation(intent)` forwards the frozen
882
+ `{role:'stt',action:'load'|'unload',reason:'user'}` record to
883
+ `requestAIRuntimeIntent()`. Before calling it, the component emits a bubbling,
884
+ composed, cancelable `speech-stt-activation-request` event with frozen
885
+ `{intent,state}` detail. `preventDefault()` suppresses the callback and intent.
886
+ Callback failure emits `speech-stt-activation-error` with frozen
887
+ `{request,error,message}` detail. Cancel loading publishes an `unload` intent;
888
+ only subsequent sticky `unloading` or `unloaded` state confirms lifecycle
889
+ progress, and callback return never proves provider work stopped.
890
+
891
+ The component emits no activation request on import or state observation.
892
+ Provider registration and selection remain inert, and default
893
+ `startTranscription=false` does not request STT during runtime startup. The
894
+ provider/runtime owner decides whether and how to execute a user intent; the
895
+ component never selects a runtime or model, downloads artifacts, reloads after
896
+ failure, or falls back to another provider.
897
+
898
+ `setAvailability()` is compatibility-only for microphone and negative
899
+ unselected-role reports. Positive STT/TTS booleans cannot manufacture a ready
900
+ role, and no compatibility value can replace a selected sticky role. Hold to
901
+ talk stays disabled without sticky ready STT, and compatibility input cannot
902
+ enable a no-selection TTS role or bypass explicit TTS activation.
903
+
904
+ Each transcription request owns an `AbortController`; its signal is passed as
905
+ the third argument to `AI.fetchSTT()`. Cancel, a newer capture, and `destroy()`
906
+ abort that controller and suppress late results. This proves request delivery
907
+ was canceled, not that an uncooperative provider stopped underlying work.
908
+
909
+ User Unmute calls the shared `AI.setSpeechMuted(false)` lifecycle owner before
910
+ or with publishing the TTS load intent, so the runtime can legally load TTS.
911
+ Mute calls `AI.setSpeechMuted(true)`, stops playback, cancels active TTS work,
912
+ and unloads the selected TTS role. Lifecycle failures remain visible through
913
+ `speech-tts-lifecycle-error` and sticky role state.
824
914
 
825
915
  ### Availability and normalization
826
916
 
827
- **Browser and supported native WebViews.** UI state normalized; AI/media behavior mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. [Deep protocol details](protocols.md).
917
+ **Browser and supported native WebViews.** UI/runtime state and explicit user
918
+ STT activation intent are normalized; provider/model authority and media
919
+ behavior remain external. HTMLImport + DOM; injected Arcane/provider modules
920
+ where listed. Native methods remain subject to the bound app's capabilities.
921
+ [Deep protocol details](protocols.md).
828
922
 
829
923
  ### Example
830
924
 
@@ -1020,19 +1114,81 @@ Events: `unified-inbox-ready`, `inbox-refresh`, `thread-select`.
1020
1114
 
1021
1115
  ### Overview
1022
1116
 
1023
- Records segmented microphone audio, transcribes, persists, and completes a combined transcript.
1117
+ Records segmented microphone audio only after authoritative STT admission,
1118
+ exposes explicit selected-STT activation, transcribes with cancellation,
1119
+ persists, and completes a combined transcript.
1024
1120
 
1025
1121
  ### Public surface
1026
1122
 
1027
- Methods/properties: `configure()`, `startRecording()`, `stopRecording()`, `save()`, `completeTranscription()/complete()`, `clear()`, `reset()`, `destroy()`.
1123
+ Methods/properties: `configure()`, `requestSTTActivation()`, `startRecording()`,
1124
+ `stopRecording()`, `save()`, `completeTranscription()/complete()`, `clear()`,
1125
+ `reset()`, `destroy()`.
1028
1126
 
1029
- Events: `voice-transcription-ready`, `voice-transcription-state`, `voice-transcription-segment`, `voice-transcription-change`, `voice-transcription-complete`, `speech-transcription-complete`.
1127
+ Events: `voice-transcription-ready`, `voice-transcription-state`,
1128
+ `voice-transcription-segment`, `voice-transcription-change`,
1129
+ `voice-transcription-complete`, `speech-transcription-complete`,
1130
+ `speech-transcription-cancelled`, `speech-stt-activation-request`, and
1131
+ `speech-stt-activation-error`.
1030
1132
 
1031
- Shared dependencies: [`MD.js`](runtime-modules.md#mdjs), [`ComponentContracts.js`](runtime-modules.md#componentcontractsjs), [`AI.js`](runtime-modules.md#aijs).
1133
+ Shared dependencies: [`MD.js`](runtime-modules.md#mdjs),
1134
+ [`ComponentContracts.js`](runtime-modules.md#componentcontractsjs),
1135
+ [`AIRuntimeState.js`](runtime-modules.md#airuntimestatejs), and
1136
+ [`AI.js`](runtime-modules.md#aijs).
1032
1137
 
1033
1138
  ### Availability and normalization
1034
1139
 
1035
- **Browser and supported native WebViews.** State/text normalized; media/provider behavior mixed. HTMLImport + DOM; injected Arcane/provider modules where listed. Native methods remain subject to the bound app's capabilities. [Deep protocol details](protocols.md).
1140
+ **Browser and supported native WebViews.** The component subscribes
1141
+ synchronously to sticky `AIRuntimeState.roles.stt`; its recording Start button
1142
+ and public `startRecording()` both fail closed unless that role is exactly
1143
+ `ready` and not busy. A configured `transcribe(file,context)` callback remains
1144
+ request plumbing rather than readiness authority. Its context now includes the
1145
+ owned `signal` additively. The default route calls
1146
+ `AI.fetchSTT(file,undefined,signal)` so the callback position remains valid and
1147
+ readiness loss or destruction can abort delivery.
1148
+
1149
+ For a selected `unloaded`, `loading`, `unloading`, or `error` role, the component
1150
+ keeps recording Start disabled and presents the same keyboard-operable Start
1151
+ transcription/Try again or Cancel loading control as `speech.html`. Both use the
1152
+ shared `createSTTActivationController()` contract. User operation emits the
1153
+ cancelable `speech-stt-activation-request` event with frozen `{intent,state}`;
1154
+ `preventDefault()` suppresses the callback. The default
1155
+ `requestSTTActivation(intent)` publishes the frozen
1156
+ `{role:'stt',action:'load'|'unload',reason:'user'}` intent. Callback failure emits
1157
+ `speech-stt-activation-error` with frozen `{request,error,message}`. Import and
1158
+ state observation emit no activation request and never begin a model download.
1159
+
1160
+ If sticky readiness is lost during microphone acquisition, capture, or the STT
1161
+ request, the component invalidates the session, aborts the owned request signal,
1162
+ releases media, discards late completion, and emits
1163
+ `speech-transcription-cancelled` with frozen `{reason:'runtime-unready'}`. A
1164
+ current provider cancellation returns the component workflow to `idle` and
1165
+ emits the same event with `reason:'stt-provider-request-cancelled'`; destroying
1166
+ an active capture or transcription emits `reason:'component-destroyed'`.
1167
+ Stale teardown results remain suppressed. A
1168
+ current save failure, including `AbortError`, enters the visible `error` state.
1169
+ Readiness loss after transcription has finished does not invalidate an already
1170
+ pending application save or completion callback: its settlement remains
1171
+ observable, while any new recording remains gated by current sticky readiness.
1172
+ Assigning `value` or calling `configure({initialValue})` explicitly supersedes
1173
+ an in-flight microphone start, STT request, save, or completion. The component
1174
+ advances its generation, aborts owned STT delivery, releases owned media, emits
1175
+ `speech-transcription-cancelled` with
1176
+ `reason:'transcript-replaced'`, and suppresses
1177
+ late settlement before publishing the assigned transcript. Assigning transcript
1178
+ text during active recording preserves that recording and changes the transcript
1179
+ to which the captured segment will be appended.
1180
+ `destroy()` aborts the state subscription, cancels active work, removes the
1181
+ activation listener, sets component `ready` to `false`, and returns `true`;
1182
+ repeated destruction is
1183
+ idempotent. Destruction is terminal: Start, activation, and Complete remain
1184
+ disabled and status remains unavailable. `voice-transcription-state` detail is
1185
+ the frozen `{message,state,stt}` record, where `state` remains the component
1186
+ workflow and `stt` is the authoritative immutable role record. Transcript
1187
+ completion stays available when STT is unavailable before destruction.
1188
+ State/text, explicit activation, and request cancellation are normalized;
1189
+ provider/model authority and media behavior remain external. HTMLImport + DOM;
1190
+ injected Arcane/provider modules where listed.
1191
+ Native methods remain subject to the bound app's capabilities. [Deep protocol details](protocols.md).
1036
1192
 
1037
1193
  ### Example
1038
1194