@pie-players/pie-assessment-toolkit 0.3.74 → 1.0.0-beta.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 (257) hide show
  1. package/README.md +658 -714
  2. package/custom-elements.json +1315 -0
  3. package/dist/attempt/TestSession.d.ts +1 -21
  4. package/dist/attempt/TestSession.js +16 -102
  5. package/dist/components/ItemScope.custom-element.d.ts +1 -0
  6. package/dist/components/ItemScope.custom-element.js +1 -0
  7. package/dist/components/ItemToolBar.custom-element.js +1 -1
  8. package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
  9. package/dist/components/SectionToolBar.custom-element.js +1 -1
  10. package/dist/components/chunks/ItemToolBar-3zrc4p3d.js +4 -0
  11. package/dist/components/chunks/ItemToolBar-66hcwmfw.js +2 -0
  12. package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
  13. package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
  14. package/dist/components/chunks/{ItemToolBar-gmrryv2v.js → ItemToolBar-kkj69ptr.js} +1 -1
  15. package/dist/components/chunks/ItemToolBar-vdkyn9f3.js +2 -0
  16. package/dist/components/chunks/sre-engine-bj997w4b.js +1 -0
  17. package/dist/components/item-scope-element.d.ts +2 -0
  18. package/dist/components/item-scope-element.js +2 -0
  19. package/dist/context/assessment-toolkit-context.d.ts +33 -6
  20. package/dist/index.d.ts +25 -50
  21. package/dist/index.js +15 -45
  22. package/dist/policy/core/PolicySource.d.ts +2 -2
  23. package/dist/policy/core/ToolPolicyEngine.d.ts +118 -34
  24. package/dist/policy/core/ToolPolicyEngine.js +203 -56
  25. package/dist/policy/core/compose-decision.d.ts +28 -7
  26. package/dist/policy/core/compose-decision.js +95 -74
  27. package/dist/policy/core/decision-types.d.ts +98 -55
  28. package/dist/policy/core/feature-decision.d.ts +28 -19
  29. package/dist/policy/core/feature-decision.js +15 -11
  30. package/dist/policy/core/pnp-policy-inputs.d.ts +29 -35
  31. package/dist/policy/core/pnp-policy-inputs.js +40 -88
  32. package/dist/policy/core/provenance.d.ts +10 -5
  33. package/dist/policy/core/provenance.js +1 -1
  34. package/dist/policy/core/tool-parameters.d.ts +11 -0
  35. package/dist/policy/core/tool-parameters.js +15 -0
  36. package/dist/policy/engine.d.ts +7 -23
  37. package/dist/policy/engine.js +5 -20
  38. package/dist/policy/sources/PnpPolicySource.d.ts +43 -68
  39. package/dist/policy/sources/PnpPolicySource.js +133 -132
  40. package/dist/runtime/SectionControllerBinding.d.ts +283 -0
  41. package/dist/runtime/SectionControllerBinding.js +456 -0
  42. package/dist/runtime/SectionRuntimeEngine.d.ts +26 -289
  43. package/dist/runtime/SectionRuntimeEngine.js +30 -372
  44. package/dist/runtime/adapter/SectionEngineAdapter.d.ts +19 -80
  45. package/dist/runtime/adapter/SectionEngineAdapter.js +19 -92
  46. package/dist/runtime/adapter/dom-event-bridge.d.ts +15 -30
  47. package/dist/runtime/adapter/dom-event-bridge.js +17 -44
  48. package/dist/runtime/adapter/subscriber-fanout.d.ts +1 -3
  49. package/dist/runtime/adapter/subscriber-fanout.js +2 -6
  50. package/dist/runtime/catalog-context.d.ts +19 -0
  51. package/dist/runtime/catalog-context.js +28 -0
  52. package/dist/runtime/composition-emit-scheduler.d.ts +12 -18
  53. package/dist/runtime/composition-emit-scheduler.js +10 -16
  54. package/dist/runtime/content-language.d.ts +32 -0
  55. package/dist/runtime/content-language.js +46 -0
  56. package/dist/runtime/content-region.d.ts +13 -0
  57. package/dist/runtime/content-region.js +29 -0
  58. package/dist/runtime/content-registration.d.ts +13 -0
  59. package/dist/runtime/content-registration.js +25 -0
  60. package/dist/runtime/core/SectionEngineCore.d.ts +2 -4
  61. package/dist/runtime/core/SectionEngineCore.js +2 -6
  62. package/dist/runtime/core/cohort.d.ts +1 -6
  63. package/dist/runtime/core/cohort.js +1 -10
  64. package/dist/runtime/core/engine-input.d.ts +18 -30
  65. package/dist/runtime/core/engine-input.js +11 -12
  66. package/dist/runtime/core/engine-output.d.ts +17 -40
  67. package/dist/runtime/core/engine-output.js +9 -21
  68. package/dist/runtime/core/engine-readiness.d.ts +5 -37
  69. package/dist/runtime/core/engine-readiness.js +8 -41
  70. package/dist/runtime/core/engine-resolver.d.ts +46 -74
  71. package/dist/runtime/core/engine-resolver.js +18 -43
  72. package/dist/runtime/core/engine-state.d.ts +28 -36
  73. package/dist/runtime/core/engine-state.js +18 -21
  74. package/dist/runtime/core/engine-transition.d.ts +14 -19
  75. package/dist/runtime/core/engine-transition.js +74 -53
  76. package/dist/runtime/engine.d.ts +16 -19
  77. package/dist/runtime/engine.js +12 -19
  78. package/dist/runtime/page-warnings.d.ts +13 -0
  79. package/dist/runtime/page-warnings.js +22 -0
  80. package/dist/runtime/policy-input-forwarding.d.ts +25 -0
  81. package/dist/runtime/policy-input-forwarding.js +25 -0
  82. package/dist/runtime/registration-events.d.ts +22 -14
  83. package/dist/runtime/runtime-event-claim.d.ts +8 -0
  84. package/dist/runtime/runtime-event-claim.js +15 -0
  85. package/dist/runtime/runtime-id.d.ts +1 -1
  86. package/dist/runtime/runtime-id.js +1 -1
  87. package/dist/runtime/shell-event-bridge.d.ts +45 -0
  88. package/dist/runtime/shell-event-bridge.js +127 -0
  89. package/dist/runtime/shell-registration.d.ts +73 -0
  90. package/dist/runtime/shell-registration.js +95 -0
  91. package/dist/runtime/shell-scope.d.ts +68 -0
  92. package/dist/runtime/shell-scope.js +194 -0
  93. package/dist/runtime/tool-host-contract.d.ts +8 -14
  94. package/dist/runtime/tool-host-contract.js +12 -12
  95. package/dist/runtime/unclaimed-registration-watch.d.ts +7 -0
  96. package/dist/runtime/unclaimed-registration-watch.js +23 -0
  97. package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
  98. package/dist/services/AccessibilityCatalogResolver.js +29 -42
  99. package/dist/services/ElementToolStateStore.d.ts +42 -67
  100. package/dist/services/ElementToolStateStore.js +65 -71
  101. package/dist/services/HighlightCoordinator.d.ts +28 -40
  102. package/dist/services/HighlightCoordinator.js +459 -381
  103. package/dist/services/RangeSerializer.d.ts +11 -33
  104. package/dist/services/RangeSerializer.js +88 -59
  105. package/dist/services/SSMLExtractor.d.ts +8 -31
  106. package/dist/services/SSMLExtractor.js +18 -40
  107. package/dist/services/TTSService.d.ts +159 -119
  108. package/dist/services/TTSService.js +937 -822
  109. package/dist/services/ToolCoordinator.d.ts +42 -102
  110. package/dist/services/ToolCoordinator.js +178 -256
  111. package/dist/services/ToolRegistry.d.ts +152 -133
  112. package/dist/services/ToolRegistry.js +192 -178
  113. package/dist/services/ToolkitCoordinator.d.ts +233 -237
  114. package/dist/services/ToolkitCoordinator.js +615 -557
  115. package/dist/services/audio-handoff.d.ts +6 -7
  116. package/dist/services/audio-handoff.js +20 -14
  117. package/dist/services/catalog-owner.d.ts +0 -1
  118. package/dist/services/framework-error-bus.d.ts +3 -6
  119. package/dist/services/framework-error-bus.js +3 -6
  120. package/dist/services/framework-error.d.ts +51 -13
  121. package/dist/services/framework-error.js +19 -20
  122. package/dist/services/interfaces.d.ts +189 -184
  123. package/dist/services/section-controller-types.d.ts +7 -7
  124. package/dist/services/section-session-assignment.d.ts +21 -0
  125. package/dist/services/section-session-assignment.js +80 -0
  126. package/dist/services/spoken-audio-cards.d.ts +2 -6
  127. package/dist/services/spoken-audio-cards.js +2 -6
  128. package/dist/services/tool-config-defaults.d.ts +3 -3
  129. package/dist/services/tool-config-defaults.js +3 -3
  130. package/dist/services/tool-config-validation.d.ts +9 -12
  131. package/dist/services/tool-config-validation.js +47 -87
  132. package/dist/services/tool-context.d.ts +7 -31
  133. package/dist/services/tool-context.js +99 -65
  134. package/dist/services/tool-failure.d.ts +30 -0
  135. package/dist/services/tool-failure.js +11 -0
  136. package/dist/services/tool-icons.d.ts +5 -5
  137. package/dist/services/tool-icons.js +6 -5
  138. package/dist/services/tool-instance-id.d.ts +8 -7
  139. package/dist/services/tool-instance-id.js +12 -24
  140. package/dist/services/tool-providers/TTSToolProvider.d.ts +20 -58
  141. package/dist/services/tool-providers/TTSToolProvider.js +32 -85
  142. package/dist/services/tool-providers/ToolProviderApi.d.ts +10 -11
  143. package/dist/services/tool-providers/ToolProviderRegistry.d.ts +29 -60
  144. package/dist/services/tool-providers/ToolProviderRegistry.js +128 -144
  145. package/dist/services/tool-request.d.ts +31 -12
  146. package/dist/services/tool-request.js +31 -16
  147. package/dist/services/toolbar-decided-tools.d.ts +16 -0
  148. package/dist/services/toolbar-decided-tools.js +29 -0
  149. package/dist/services/toolbar-items.js +2 -5
  150. package/dist/services/tools-config-normalizer.d.ts +33 -29
  151. package/dist/services/tools-config-normalizer.js +26 -28
  152. package/dist/services/tts/browser-provider.d.ts +39 -6
  153. package/dist/services/tts/browser-provider.js +280 -160
  154. package/dist/services/tts/catalog-span-alignment.js +14 -7
  155. package/dist/services/tts/flat-tree.d.ts +64 -0
  156. package/dist/services/tts/flat-tree.js +269 -0
  157. package/dist/services/tts/generated-speech/assemble-plan.d.ts +3 -1
  158. package/dist/services/tts/generated-speech/assemble-plan.js +3 -1
  159. package/dist/services/tts/generated-speech/dom/build-dom-plan.d.ts +2 -0
  160. package/dist/services/tts/generated-speech/dom/build-dom-plan.js +1 -1
  161. package/dist/services/tts/generated-speech/dom/to-chunk-inputs.d.ts +2 -2
  162. package/dist/services/tts/generated-speech/index.d.ts +1 -1
  163. package/dist/services/tts/generated-speech/index.js +1 -1
  164. package/dist/services/tts/generated-speech/math-speech-cache.d.ts +3 -1
  165. package/dist/services/tts/generated-speech/math-speech-cache.js +5 -1
  166. package/dist/services/tts/generated-speech/types.d.ts +1 -1
  167. package/dist/services/tts/generated-speech/types.js +1 -1
  168. package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +22 -16
  169. package/dist/services/tts/highlight-pipeline/prose-boundary-resolver.js +6 -4
  170. package/dist/services/tts/highlight-pipeline/readable-region.js +3 -2
  171. package/dist/services/tts/highlight-pipeline/types.d.ts +5 -0
  172. package/dist/services/tts/highlight-pipeline/visible-map-range.d.ts +12 -0
  173. package/dist/services/tts/highlight-pipeline/visible-map-range.js +73 -7
  174. package/dist/services/tts/highlight-target-resolver.d.ts +12 -0
  175. package/dist/services/tts/math-aware-text-processing.d.ts +5 -1
  176. package/dist/services/tts/math-aware-text-processing.js +42 -47
  177. package/dist/services/tts/math-control-names.d.ts +21 -0
  178. package/dist/services/tts/math-control-names.js +142 -0
  179. package/dist/services/tts/math-speech.d.ts +12 -1
  180. package/dist/services/tts/math-speech.js +54 -18
  181. package/dist/services/tts/mathml-sanitization.d.ts +7 -0
  182. package/dist/services/tts/mathml-sanitization.js +9 -1
  183. package/dist/services/tts/provider-options.d.ts +52 -0
  184. package/dist/services/tts/provider-options.js +1 -0
  185. package/dist/services/tts/ssml/spoken-text.d.ts +2 -26
  186. package/dist/services/tts/ssml/spoken-text.js +29 -0
  187. package/dist/services/tts/start-failure.d.ts +4 -0
  188. package/dist/services/tts/start-failure.js +19 -0
  189. package/dist/services/tts/text-processing.d.ts +9 -0
  190. package/dist/services/tts/text-processing.js +46 -33
  191. package/dist/services/tts/text-segmentation.d.ts +12 -0
  192. package/dist/services/tts/text-segmentation.js +60 -10
  193. package/dist/services/tts-runtime-config.d.ts +54 -26
  194. package/dist/services/tts-runtime-config.js +27 -112
  195. package/dist/tools/content-capability-resolution.d.ts +9 -11
  196. package/dist/tools/content-capability-resolution.js +8 -45
  197. package/dist/tools/registration.d.ts +59 -0
  198. package/dist/tools/registration.js +55 -0
  199. package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
  200. package/dist/tools/registrations/toolbar-registration-helpers.js +8 -2
  201. package/dist/tools/tool-surface-host.d.ts +6 -10
  202. package/dist/tools/tool-surface-host.js +45 -50
  203. package/dist/tools/tool-tag-map.d.ts +5 -15
  204. package/dist/tools/tool-tag-map.js +6 -20
  205. package/dist/utils/structural-equality.d.ts +11 -0
  206. package/dist/utils/structural-equality.js +47 -0
  207. package/package.json +15 -29
  208. package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts +0 -49
  209. package/dist/attempt/adapters/activity-to-test-attempt-session.js +0 -138
  210. package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +0 -40
  211. package/dist/components/chunks/ItemToolBar-h4xap0t0.js +0 -4
  212. package/dist/components/chunks/ItemToolBar-wr2myaah.js +0 -2
  213. package/dist/components/chunks/sre-engine-wf9s43gg.js +0 -1
  214. package/dist/context/runtime-context-consumer.d.ts +0 -13
  215. package/dist/context/runtime-context-consumer.js +0 -18
  216. package/dist/item-loader.d.ts +0 -44
  217. package/dist/item-loader.js +0 -61
  218. package/dist/policy/core/engine-context.d.ts +0 -29
  219. package/dist/policy/core/engine-context.js +0 -27
  220. package/dist/policy/core/policy-source-tag.d.ts +0 -31
  221. package/dist/policy/core/policy-source-tag.js +0 -28
  222. package/dist/policy/internal.d.ts +0 -25
  223. package/dist/policy/internal.js +0 -25
  224. package/dist/runtime/adapter/coordinator-bridge.d.ts +0 -92
  225. package/dist/runtime/adapter/coordinator-bridge.js +0 -126
  226. package/dist/runtime/adapter/framework-error-bridge.d.ts +0 -36
  227. package/dist/runtime/adapter/framework-error-bridge.js +0 -46
  228. package/dist/runtime/adapter/instrumentation-bridge.d.ts +0 -31
  229. package/dist/runtime/adapter/instrumentation-bridge.js +0 -38
  230. package/dist/runtime/core/engine-stage-derivation.d.ts +0 -18
  231. package/dist/runtime/core/engine-stage-derivation.js +0 -29
  232. package/dist/runtime/engine-context.d.ts +0 -39
  233. package/dist/runtime/engine-context.js +0 -31
  234. package/dist/runtime/internal.d.ts +0 -43
  235. package/dist/runtime/internal.js +0 -45
  236. package/dist/runtime/section-runtime-engine-host-context.d.ts +0 -74
  237. package/dist/runtime/section-runtime-engine-host-context.js +0 -57
  238. package/dist/runtime/stage-emit-gate.d.ts +0 -92
  239. package/dist/runtime/stage-emit-gate.js +0 -82
  240. package/dist/services/ContextVariableStore.d.ts +0 -113
  241. package/dist/services/ContextVariableStore.js +0 -206
  242. package/dist/services/I18nService.d.ts +0 -47
  243. package/dist/services/I18nService.js +0 -84
  244. package/dist/services/ThemeProvider.d.ts +0 -95
  245. package/dist/services/ThemeProvider.js +0 -334
  246. package/dist/services/defaultPersonalNeedsProfile.d.ts +0 -21
  247. package/dist/services/defaultPersonalNeedsProfile.js +0 -26
  248. package/dist/services/pnp-standard-features.d.ts +0 -238
  249. package/dist/services/pnp-standard-features.js +0 -338
  250. package/dist/services/tts-control-events.d.ts +0 -13
  251. package/dist/services/tts-control-events.js +0 -7
  252. package/dist/tools/client.d.ts +0 -10
  253. package/dist/tools/client.js +0 -10
  254. package/dist/tools/internal.d.ts +0 -44
  255. package/dist/tools/internal.js +0 -39
  256. package/dist/utils/logger.d.ts +0 -6
  257. package/dist/utils/logger.js +0 -10
@@ -1,20 +1,28 @@
1
1
  /**
2
- * ToolkitCoordinator - Centralized Assessment Toolkit Service Management
2
+ * ToolkitCoordinator: one per assessment, the owner of every toolkit service
3
+ * (TTSService, ToolCoordinator, HighlightCoordinator, ElementToolStateStore,
4
+ * AccessibilityCatalogResolver, ToolProviderRegistry), the ToolPolicyEngine,
5
+ * the framework-error bus and the section controllers. It holds toolkit
6
+ * concerns only; navigation, timing and progress belong to the player.
3
7
  *
4
- * Orchestrates all toolkit services (TTS, tools, accessibility, state management) from a single entry point.
5
- * Provides centralized configuration for tool availability and settings.
6
- *
7
- * Key features:
8
- * - Owns all toolkit services (TTSService, ToolCoordinator, HighlightCoordinator, ElementToolStateStore, AccessibilityCatalogResolver)
9
- * - Single configuration point for tool availability and settings
10
- * - Sensible defaults for standalone usage
11
- * - Direct access for settings widgets (no player dependency)
12
- * - Clean separation: toolkit concerns only (NOT assessment state like navigation, timing, progress)
13
- *
14
- * Part of PIE Assessment Toolkit.
8
+ * Layout: the module's exported config, hook and event types come first, then
9
+ * the class, whose members run in this order:
10
+ * - config resolution and the constructor;
11
+ * - error, telemetry and tool-failure reporting, readiness listeners and the
12
+ * framework-error bus;
13
+ * - element tool-state persistence;
14
+ * - tool registry adoption and provider registration;
15
+ * - section-event subscriptions, which follow the active cohort;
16
+ * - section controller creation, publication and disposal;
17
+ * - coordinator disposal;
18
+ * - TTS bring-up and readiness;
19
+ * - tool config updates and the policy engine surface, with the tool-context
20
+ * resolvers split around it (installation before, queries after);
21
+ * - tool-open requests;
22
+ * - config-change application and TTS reconfiguration, last.
15
23
  */
16
- import type { AccessibilityCatalog, AssessmentEntity, AssessmentItemRef } from "@pie-players/pie-players-shared/types";
17
- import { type CanonicalToolsConfig, type ToolPlacementConfig, type ToolPlacementLevel, type ToolPolicyConfig, type TextToSpeechToolProviderConfig, type ToolProviderConfig, type ToolProvidersConfig, type ToolsConfigInput } from "./tools-config-normalizer.js";
24
+ import type { AccessibilityCatalog, AssessmentEntity, ItemSettings, ToolParametersFor } from "@pie-players/pie-players-shared/types";
25
+ import { type CanonicalToolsConfig, type ToolPlacementConfig, type ToolPolicyConfig, type TextToSpeechToolProviderConfig, type ToolProviderConfig, type ToolProvidersConfig, type ToolsConfigInput } from "./tools-config-normalizer.js";
18
26
  import { type ToolConfigStrictness } from "./tool-config-validation.js";
19
27
  import { AccessibilityCatalogResolver } from "./AccessibilityCatalogResolver.js";
20
28
  import type { CatalogChangeListener } from "./AccessibilityCatalogResolver.js";
@@ -22,55 +30,18 @@ import { ElementToolStateStore } from "./ElementToolStateStore.js";
22
30
  import { type FrameworkErrorModel } from "./framework-error.js";
23
31
  import { FrameworkErrorBus, type FrameworkErrorListener } from "./framework-error-bus.js";
24
32
  import { HighlightCoordinator } from "./HighlightCoordinator.js";
25
- import { ToolCoordinator } from "./ToolCoordinator.js";
33
+ import type { ToolCoordinatorApi } from "./interfaces.js";
26
34
  import { TTSService } from "./TTSService.js";
27
- import { type TTSRuntimeSettings } from "./tts-runtime-config.js";
28
- import type { SREMathSpeechOptions } from "./tts/math-speech.js";
29
35
  import { ToolProviderRegistry } from "./tool-providers/index.js";
30
36
  import type { ToolProviderApi } from "./tool-providers/ToolProviderApi.js";
31
37
  import { ToolRegistry } from "./ToolRegistry.js";
32
- import type { ResolvedToolContext, ToolContextResolver, ToolContextResolverContext, ToolContextResolverMap } from "./ToolRegistry.js";
38
+ import type { ResolvedToolContext, ToolContextResolverContext, ToolContextResolverMap } from "./ToolRegistry.js";
39
+ import type { ToolFailurePhase } from "./tool-failure.js";
33
40
  import type { ToolOpenRequest, ToolRequestTarget } from "./tool-request.js";
34
- import { type FeaturePolicyDecision, type PnpEnforcementMode, type PolicySource, type ResolvedEngineInputs, type ToolPolicyChangeListener, type ToolPolicyDecision, type ToolPolicyDecisionRequest } from "../policy/engine.js";
35
- import type { SectionControllerContext, SectionControllerEvent, SectionControllerEventType, SectionControllerFactoryDefaults, SectionControllerHandle, SectionControllerKey, SectionSessionPersistenceStrategy, SectionPersistenceFactoryDefaults } from "./section-controller-types.js";
41
+ import { type FeaturePolicyDecision, type PnpEnforcementMode, type PolicySource, type ResolvedEngineInputs, type ToolPolicyChangeListener, type ToolPolicyDecision, type ToolPolicyDecisionRequest, type ToolPolicyDiagnostic, type ToolScope } from "../policy/engine.js";
42
+ import type { SectionControllerContext, SectionControllerEvent, SectionControllerEventType, SectionControllerFactoryDefaults, SectionControllerHandle, SectionControllerKey, SectionControllerSessionState, SectionSessionPersistenceStrategy, SectionPersistenceFactoryDefaults } from "./section-controller-types.js";
36
43
  export type { SectionControllerContext, SectionControllerEvent, SectionControllerEventType, SectionControllerFactoryDefaults, SectionControllerHandle, SectionControllerKey, SectionControllerLoadedRenderable, SectionSessionPersistenceConfig, SectionSessionPersistenceStrategy, SectionControllerRuntimeState, SectionControllerSessionState, SectionPersistenceFactoryDefaults, } from "./section-controller-types.js";
37
44
  export type { FeaturePolicyDecision, PnpEnforcementMode, ResolvedEngineInputs, ToolPolicyChangeListener, ToolPolicyDecision, ToolPolicyDecisionRequest, } from "../policy/engine.js";
38
- /**
39
- * Generic tool configuration
40
- */
41
- export interface ToolConfig {
42
- enabled?: boolean;
43
- provider?: unknown;
44
- settings?: Record<string, unknown>;
45
- [key: string]: unknown;
46
- }
47
- /**
48
- * TTS configuration as a host writes it.
49
- *
50
- * The field set is `TTSRuntimeSettings`, which the runtime resolver owns: the two
51
- * were declared separately and had already drifted in both directions, so a field
52
- * the runtime honoured could not be named here. What this adds is the one thing
53
- * only a host-facing config has — a place to stash unrecognised keys, which the
54
- * resolved runtime settings do not carry.
55
- *
56
- * `provider` is typed from the `textToSpeech` tools-config entry instead: a host
57
- * gives either a server provider id or a runtime provider object, whose
58
- * `runtime.authFetcher` the TTS registration reads, and `TTSRuntimeSettings`
59
- * names only the id. The entry is therefore assignable to this type, which is
60
- * what `getToolConfig("textToSpeech")` returns.
61
- */
62
- export type TTSToolConfig = ToolConfig & Omit<TTSRuntimeSettings, "provider"> & {
63
- provider?: TextToSpeechToolProviderConfig["provider"];
64
- settings?: Record<string, unknown> & {
65
- mathSpeech?: SREMathSpeechOptions;
66
- };
67
- };
68
- /**
69
- * Answer eliminator tool configuration
70
- */
71
- export interface AnswerEliminatorToolConfig extends ToolConfig {
72
- strategy?: "strikethrough" | "hide";
73
- }
74
45
  export interface ToolkitToolsConfig extends CanonicalToolsConfig {
75
46
  policy: ToolPolicyConfig;
76
47
  placement: Required<ToolPlacementConfig>;
@@ -86,8 +57,8 @@ export interface ToolkitCoordinatorConfig {
86
57
  */
87
58
  assessmentId: string;
88
59
  /**
89
- * Tool availability and configuration.
90
- * Defaults: all tools enabled with default settings.
60
+ * Tool availability and configuration. The default placement is empty: a tool
61
+ * shows only where placement puts it, and a grant does not place one.
91
62
  */
92
63
  tools?: ToolsConfigInput;
93
64
  /**
@@ -129,12 +100,21 @@ export interface ToolkitCoordinatorConfig {
129
100
  */
130
101
  hooks?: ToolkitCoordinatorHooks;
131
102
  /**
132
- * Lazy initialization mode.
133
- * When true, async service/provider initialization is deferred until ensure methods are called.
103
+ * Start text-to-speech at its first use rather than as part of readiness.
104
+ * `waitUntilReady()` then settles without it, unless policy grants the tool,
105
+ * so a granted read-aloud still fails before the learner starts.
134
106
  *
135
107
  * @default false
136
108
  */
137
109
  lazyInit?: boolean;
110
+ /**
111
+ * Start initializing at construction. `<pie-assessment-toolkit>` passes false
112
+ * for the coordinator it builds, and starts initialization once its section
113
+ * composes.
114
+ *
115
+ * @default !lazyInit
116
+ */
117
+ eagerInit?: boolean;
138
118
  /**
139
119
  * Internal bootstrap escape hatch used by framework-owned hosts.
140
120
  * When true, constructor skips throwing validation and expects caller
@@ -166,20 +146,15 @@ export interface ToolkitCoordinatorConfig {
166
146
  frameworkErrorBus?: FrameworkErrorBus;
167
147
  }
168
148
  export interface ToolkitErrorContext {
169
- phase: "coordinator-ready" | "state-load" | "state-save" | "provider-register" | "provider-init" | "tts-init" | "section-controller-init" | "section-controller-dispose";
170
- providerId?: string;
149
+ phase: "coordinator-ready" | "state-load" | "state-save" | "provider-register" | "provider-init" | "tts-init" | "section-controller-init" | "section-controller-dispose" | ToolFailurePhase;
150
+ /** The tool whose provider failed. */
151
+ toolId?: string;
171
152
  details?: Record<string, unknown>;
153
+ recoverable?: boolean;
172
154
  }
173
155
  export interface ProviderLifecycleContext {
174
- providerId: string;
175
156
  providerName?: string;
176
157
  }
177
- export interface ToolkitInitStatus {
178
- tts: boolean;
179
- stateLoaded: boolean;
180
- coordinator: boolean;
181
- providers: Record<string, boolean>;
182
- }
183
158
  export interface SectionControllerLifecycleEvent {
184
159
  type: "ready" | "disposed";
185
160
  key: SectionControllerKey;
@@ -188,8 +163,8 @@ export interface SectionControllerLifecycleEvent {
188
163
  /**
189
164
  * Subscribe-time arguments for {@link ToolkitCoordinator.subscribeSectionEvents}.
190
165
  *
191
- * Phase D contract: subscriptions follow the toolkit's *active section
192
- * cohort* automatically. The listener is bound to whatever section
166
+ * Subscriptions follow the toolkit's *active section cohort*
167
+ * automatically. The listener is bound to whatever section
193
168
  * controller is active at subscribe time and is migrated, with snapshot
194
169
  * replay, on every cohort transition. There is no per-subscription
195
170
  * `(sectionId, attemptId)` binding.
@@ -210,8 +185,8 @@ export type SectionScopedEvent = Extract<SectionControllerEvent, {
210
185
  /**
211
186
  * Subscribe-time arguments for {@link ToolkitCoordinator.subscribeItemEvents}.
212
187
  *
213
- * See {@link SectionEventSubscriptionArgs} for the Phase D active-cohort
214
- * binding contract.
188
+ * See {@link SectionEventSubscriptionArgs} for the active-cohort binding
189
+ * contract.
215
190
  */
216
191
  export interface SectionItemEventSubscriptionArgs {
217
192
  listener: (event: SectionItemEvent) => void;
@@ -222,8 +197,8 @@ export interface SectionItemEventSubscriptionArgs {
222
197
  * Subscribe-time arguments for
223
198
  * {@link ToolkitCoordinator.subscribeSectionLifecycleEvents}.
224
199
  *
225
- * See {@link SectionEventSubscriptionArgs} for the Phase D active-cohort
226
- * binding contract.
200
+ * See {@link SectionEventSubscriptionArgs} for the active-cohort binding
201
+ * contract.
227
202
  */
228
203
  export interface SectionScopedEventSubscriptionArgs {
229
204
  listener: (event: SectionScopedEvent) => void;
@@ -249,9 +224,9 @@ export interface ToolkitCoordinatorHooks {
249
224
  onBeforeTTSInit?: (context: ToolkitErrorContext) => void | Promise<void>;
250
225
  onTTSReady?: () => void | Promise<void>;
251
226
  onCoordinatorReady?: (coordinator: ToolkitCoordinator) => void | Promise<void>;
252
- onProviderRegistered?: (providerId: string, meta: ProviderLifecycleContext) => void | Promise<void>;
253
- onProviderInitStart?: (providerId: string, meta: ProviderLifecycleContext) => void | Promise<void>;
254
- onProviderReady?: (providerId: string, meta: ProviderLifecycleContext) => void | Promise<void>;
227
+ onProviderRegistered?: (toolId: string, meta: ProviderLifecycleContext) => void | Promise<void>;
228
+ onProviderInitStart?: (toolId: string, meta: ProviderLifecycleContext) => void | Promise<void>;
229
+ onProviderReady?: (toolId: string, meta: ProviderLifecycleContext) => void | Promise<void>;
255
230
  onTelemetry?: (eventName: string, payload?: Record<string, unknown>) => void | Promise<void>;
256
231
  loadToolState?: () => Record<string, Record<string, unknown>> | Promise<Record<string, Record<string, unknown>> | null | undefined> | null | undefined;
257
232
  saveToolState?: (state: Record<string, Record<string, unknown>>) => void | Promise<void>;
@@ -269,23 +244,12 @@ export type ToolkitTelemetryListener = (args: {
269
244
  eventName: string;
270
245
  payload?: Record<string, unknown>;
271
246
  }) => void;
272
- /**
273
- * Service bundle returned by getServiceBundle()
274
- */
275
- export interface ToolkitServiceBundle {
276
- ttsService: TTSService;
277
- toolCoordinator: ToolCoordinator;
278
- highlightCoordinator: HighlightCoordinator;
279
- elementToolStateStore: ElementToolStateStore;
280
- catalogResolver: AccessibilityCatalogResolver;
281
- toolProviderRegistry: ToolProviderRegistry;
282
- }
283
247
  /**
284
248
  * ToolkitCoordinator - Orchestrates all assessment toolkit services
285
249
  *
286
250
  * @example
287
251
  * ```typescript
288
- * // createPackagedToolRegistry is exported by @pie-players/pie-default-tool-loaders
252
+ * // Exported by @pie-players/pie-default-tool-loaders
289
253
  * const toolRegistry = createPackagedToolRegistry();
290
254
  *
291
255
  * // Create coordinator with configuration
@@ -295,7 +259,7 @@ export interface ToolkitServiceBundle {
295
259
  * tools: {
296
260
  * providers: {
297
261
  * textToSpeech: { enabled: true, backend: 'browser' },
298
- * answerEliminator: { enabled: true, strategy: 'strikethrough' }
262
+ * answerEliminator: { enabled: true }
299
263
  * },
300
264
  * placement: {
301
265
  * item: ['textToSpeech', 'answerEliminator']
@@ -318,7 +282,7 @@ export declare class ToolkitCoordinator {
318
282
  readonly config: ToolkitCoordinatorConfig;
319
283
  /** Managed services (public for direct access) */
320
284
  readonly ttsService: TTSService;
321
- readonly toolCoordinator: ToolCoordinator;
285
+ readonly toolCoordinator: ToolCoordinatorApi;
322
286
  readonly highlightCoordinator: HighlightCoordinator;
323
287
  readonly elementToolStateStore: ElementToolStateStore;
324
288
  readonly catalogResolver: AccessibilityCatalogResolver;
@@ -327,22 +291,42 @@ export declare class ToolkitCoordinator {
327
291
  readonly lazyInit: boolean;
328
292
  /** Track TTS initialization state */
329
293
  private ttsInitialized;
294
+ /** Text-to-speech failed to start and policy does not grant it. */
295
+ private ttsDegraded;
330
296
  private ttsInitPromise?;
331
297
  private ttsReconfigurePromise?;
332
- private stateLoaded;
298
+ /**
299
+ * The loader ran, whether or not it returned state. A failed load is
300
+ * reported once and the coordinator runs without saved tool state.
301
+ */
302
+ private stateLoadSettled;
333
303
  private stateLoadPromise?;
334
304
  private coordinatorReadyPromise?;
335
305
  private coordinatorReadyNotified;
336
306
  private readonly providerInitPromises;
307
+ /**
308
+ * Recoverable failures, by tool. A policy change that grants one of these
309
+ * tools reports its failure again as fatal.
310
+ */
311
+ private readonly degradedTools;
312
+ /** Tool failures already reported, by phase and tool, each reported once. */
313
+ private readonly reportedToolFailures;
314
+ private readonly readyChangeListeners;
315
+ private readonly eagerInit;
337
316
  private toolRegistry;
338
317
  /** Whether the host passed `toolRegistry`, which then always stands. */
339
318
  private readonly toolRegistrySupplied;
340
319
  /**
341
320
  * Whether the registry is final: supplied at construction, or adopted from
342
- * the toolkit this coordinator is bound to. Until then the empty placeholder
343
- * reports no missing registry, since the toolkit will supply one.
321
+ * the toolkit this coordinator is bound to.
344
322
  */
345
323
  private toolRegistrySettled;
324
+ /**
325
+ * Whether a bound toolkit reported having no registry. Until then, or until a
326
+ * registry settles, the empty placeholder reports no missing registry, since
327
+ * the toolkit may supply one.
328
+ */
329
+ private toolRegistryAbsent;
346
330
  private readonly toolContextResolvers;
347
331
  private readonly toolContextResolverChangeListeners;
348
332
  private readonly toolRequests;
@@ -353,8 +337,8 @@ export declare class ToolkitCoordinator {
353
337
  private readonly sectionPersistenceStrategies;
354
338
  private readonly sectionControllerLifecycleListeners;
355
339
  /**
356
- * Phase D: every active section-event subscription, indexed by
357
- * listener identity. The listener follows the toolkit's active
340
+ * Every active section-event subscription, indexed by listener
341
+ * identity. The listener follows the toolkit's active
358
342
  * section cohort across transitions; this map is the registry the
359
343
  * coordinator iterates on every cohort change to detach the listener
360
344
  * from the outgoing controller, attach it to the new one, and replay
@@ -366,22 +350,26 @@ export declare class ToolkitCoordinator {
366
350
  */
367
351
  private readonly activeSubscriptions;
368
352
  /**
369
- * Phase D: map key of the section controller currently treated as
370
- * the *active cohort*. Set by `getOrCreateSectionController` (both
353
+ * Map key of the section controller currently treated as the
354
+ * *active cohort*. Set by `getOrCreateSectionController` (both
371
355
  * the create-new and resolve-existing paths) and cleared when the
372
- * matching controller is disposed. `null` while no cohort exists,
373
- * which is the only state where `subscribeSectionEvents` throws.
356
+ * matching controller is disposed, and `null` while the next requested
357
+ * cohort is still starting.
374
358
  */
375
359
  private activeCohortMapKey;
376
360
  /**
377
361
  * Latest requested active cohort. Async controller initialization can
378
362
  * resolve out of order; only the most recent request may migrate active
379
363
  * subscriptions. Older completions still populate the controller cache.
364
+ * `null` until the first request, which is the only state where
365
+ * `subscribeSectionEvents` throws.
380
366
  */
381
367
  private latestRequestedActiveCohortMapKey;
382
368
  private readonly telemetryListeners;
383
369
  private readonly frameworkErrorBus;
384
370
  private readonly ownsFrameworkErrorBus;
371
+ /** The instance behind {@link toolCoordinator}, kept for disposal. */
372
+ private readonly ownedToolCoordinator;
385
373
  private frameworkErrorHookUnsubscribe;
386
374
  private disposePromise;
387
375
  /**
@@ -392,32 +380,12 @@ export declare class ToolkitCoordinator {
392
380
  */
393
381
  private readonly policyEngine;
394
382
  /**
395
- * Host-set override for PNP/profile enforcement. `null` (the default) means
396
- * "auto" — the coordinator infers the effective mode from the
397
- * PNP/profile policy inputs the bound `AssessmentEntity` and `AssessmentItemRef`
398
- * actually carry (see {@link resolveEffectivePnpEnforcement}).
399
- * `"on"` / `"off"` are explicit host opt-in / opt-out and stick
400
- * across subsequent assessment / item swaps until the host clears
401
- * the override by calling `setPnpEnforcement(null)`.
402
- */
403
- private pnpEnforcementOverride;
404
- /**
405
- * Last assessment passed to {@link updateAssessment}. Read by
406
- * {@link resolveEffectivePnpEnforcement} to compute auto-mode.
407
- * The engine's own copy is the canonical record for decisions;
408
- * this mirror exists only so the auto-mode helper does not need
409
- * to round-trip through {@link policyEngine}'s frozen snapshot.
410
- */
411
- private boundAssessment;
412
- /**
413
- * Last item reference passed to {@link updateCurrentItemRef}.
414
- * Mirrored alongside {@link boundAssessment} so
415
- * {@link resolveEffectivePnpEnforcement} can detect item-level
416
- * profile policy inputs (`requiredTools` / `restrictedTools` /
417
- * `toolParameters`) without round-tripping through the engine's
418
- * frozen snapshot.
383
+ * Policy diagnostics reported since the last input change, keyed by code,
384
+ * tool id and, for `tool-policy.itemSettingNotApplied`, item id; see
385
+ * {@link warnPolicyDiagnostics}.
419
386
  */
420
- private boundCurrentItemRef;
387
+ private readonly reportedPolicyDiagnostics;
388
+ private readonly policyDiagnosticListeners;
421
389
  /**
422
390
  * Whether {@link decideFeaturePolicy} has already reported serving a decision
423
391
  * with no assessment bound.
@@ -431,7 +399,7 @@ export declare class ToolkitCoordinator {
431
399
  private reportedUnboundFeaturePolicy;
432
400
  /**
433
401
  * Whether {@link _initializeTTS} has already reported a non-browser backend
434
- * falling back to browser speech because no `tts` provider is registered.
402
+ * falling back to browser speech because no text-to-speech provider is registered.
435
403
  * Once per coordinator: a text-to-speech config change re-runs
436
404
  * initialization, and the missing provider is the same gap each time.
437
405
  */
@@ -490,7 +458,42 @@ export declare class ToolkitCoordinator {
490
458
  */
491
459
  private emitTelemetry;
492
460
  private emitSectionControllerLifecycle;
461
+ /**
462
+ * Every report site states whether the coordinator carries on after the
463
+ * failure; one that takes down only its section passes that section.
464
+ */
493
465
  private handleError;
466
+ /**
467
+ * Whether policy grants `toolId` as an accommodation on some surface: a
468
+ * test-administration override, a mounted item's or a district requirement,
469
+ * or profile support. A toolbar tool counts only surfaces where PNP
470
+ * enforcement is on; a region feature ignores enforcement, as its decisions
471
+ * do. Read without the unbound-assessment warning.
472
+ */
473
+ private isToolGranted;
474
+ /**
475
+ * Reports a tool's start failure: recoverable, so the tool reports itself
476
+ * unavailable and the assessment goes on, unless policy grants the tool.
477
+ * `fallbackFollows` marks a failure another path absorbs, which is recoverable
478
+ * whatever the policy.
479
+ */
480
+ private reportStartFailure;
481
+ /**
482
+ * Report that a tool failed in `phase`. A module that failed to load follows
483
+ * the start-failure policy: the tool degrades, so toolbars withhold it, unless
484
+ * policy grants it. Every other phase is recoverable, since its report site
485
+ * keeps a recovery, and is reported on a microtask. Reported once per tool and
486
+ * phase however many toolbars or instances fail. A module failure re-announces the request targets, since
487
+ * the reporting toolbar no longer hosts the tool.
488
+ */
489
+ reportToolFailure(toolId: string, phase: ToolFailurePhase, error: unknown): void;
490
+ private reportNewlyGrantedFailures;
491
+ /**
492
+ * Subscribe to changes of {@link isReady}: state loading, text-to-speech
493
+ * starting, failing or reconfiguring. The listener reads the status itself.
494
+ */
495
+ onReadyChange(listener: () => void): () => void;
496
+ private notifyReadyChange;
494
497
  /**
495
498
  * Subscribe to framework-error events emitted by this coordinator.
496
499
  *
@@ -516,43 +519,47 @@ export declare class ToolkitCoordinator {
516
519
  * @internal
517
520
  */
518
521
  reportFrameworkError(model: FrameworkErrorModel): void;
522
+ private sectionControllerKey;
519
523
  private getSectionControllerMapKey;
520
524
  private createDefaultSectionPersistence;
521
525
  private resolveSectionPersistence;
522
526
  private setupStatePersistenceHooks;
523
527
  private ensureStateLoaded;
528
+ /** Whether the toolkit this coordinator binds to may still supply a registry. */
529
+ private toolRegistryPending;
524
530
  private reportMissingTTSProvider;
525
531
  /**
526
532
  * Take the registry of the toolkit this coordinator is bound to, when the host
527
533
  * constructed it without one: the config is validated against it, its
528
534
  * providers register, and text-to-speech re-initializes through it if it
529
- * already started. The toolkit elements call this on binding. A registry
530
- * passed at construction stands, and the first call wins; `null` records a
531
- * toolkit without one, which reports the registry as missing.
535
+ * already started. The toolkit elements call this on binding, and again when
536
+ * their registry changes. A registry passed at construction stands, and the
537
+ * first registry adopted wins; `null` records a toolkit without one, which
538
+ * reports the registry as missing and still adopts one that arrives later.
532
539
  *
533
540
  * @returns Whether `registry` was adopted.
534
541
  */
535
542
  adoptToolRegistry(registry: ToolRegistry | null): boolean;
536
- /**
537
- * Register tool providers in the registry
538
- */
539
543
  private _registerToolProviders;
540
544
  private getProviderDescriptorTools;
541
545
  /**
542
546
  * Register the provider `tool`'s descriptor creates for the tool's current
543
- * config, unless the tool is disabled or that provider id is registered. A
544
- * descriptor that throws is reported the way a failed registration is.
547
+ * config under the tool's id, unless the tool is disabled or, without
548
+ * `replace`, a provider is registered under that id. A descriptor that throws
549
+ * is reported the way a failed registration is.
545
550
  */
546
551
  private registerProviderFromTool;
547
552
  private createToolTelemetryForwarder;
548
553
  private addToolTelemetryReporter;
549
554
  private registerProvider;
550
555
  /**
551
- * A console warning and a `provider-register` framework error. `providerId`
552
- * is null when resolving it is what failed; the warning names the tool then.
556
+ * A console warning and a `provider-register` framework error, under the
557
+ * start-failure policy every other tool failure follows.
553
558
  */
554
559
  private reportProviderRegisterFailure;
555
- ensureProviderReady(providerId: string): Promise<ToolProviderApi>;
560
+ ensureProviderReady(toolId: string): Promise<ToolProviderApi>;
561
+ /** `fallbackFollows`: the caller recovers from a failure on its own. */
562
+ private initializeProvider;
556
563
  setHooks(hooks: ToolkitCoordinatorHooks): void;
557
564
  subscribeTelemetry(listener: ToolkitTelemetryListener): () => void;
558
565
  getSectionController(args: {
@@ -561,7 +568,7 @@ export declare class ToolkitCoordinator {
561
568
  }): SectionControllerHandle | undefined;
562
569
  subscribeSectionEvents(args: SectionEventSubscriptionArgs): () => void;
563
570
  /**
564
- * Bind a Phase D subscription to a section controller. Detaches any
571
+ * Bind an active-cohort subscription to a section controller. Detaches any
565
572
  * prior controller binding the subscription was holding, attaches a
566
573
  * fresh `controller.subscribe(...)` callback, and replays the
567
574
  * canonical late-subscribe sequence (content-loaded × N then
@@ -594,6 +601,12 @@ export declare class ToolkitCoordinator {
594
601
  * re-bind them to the new controller.
595
602
  */
596
603
  private clearActiveCohortIfMatches;
604
+ /**
605
+ * Detach every active subscription from its controller. Iterates a snapshot,
606
+ * as `setActiveCohort` does, because a disposer may mutate
607
+ * `activeSubscriptions`.
608
+ */
609
+ private detachActiveSubscriptions;
597
610
  private buildSectionEventPredicate;
598
611
  private collectEventItemIds;
599
612
  /**
@@ -636,17 +649,31 @@ export declare class ToolkitCoordinator {
636
649
  attemptId?: string;
637
650
  input?: unknown;
638
651
  updateExisting?: boolean;
652
+ initialSession?: SectionControllerSessionState | null;
639
653
  createDefaultController: () => SectionControllerHandle | Promise<SectionControllerHandle>;
640
654
  }): Promise<SectionControllerHandle>;
641
655
  private resolveExistingSectionController;
642
656
  private createSectionControllerContext;
643
657
  private initializeNewSectionController;
658
+ /**
659
+ * Apply a host-supplied session to a controller that is already published,
660
+ * under the rules `resolveSectionSessionAssignment` sets: an equal session is a
661
+ * no-op and recorded responses are not replaced by response-free ones.
662
+ */
663
+ private assignSessionToPublishedController;
644
664
  private createSectionControllerRetirementError;
645
665
  private retireUnpublishedSectionControllerIfNeeded;
646
666
  private cleanupUnpublishedSectionController;
647
667
  private retirePublishedSectionControllerIfNeeded;
648
668
  private finalizeSectionControllerReady;
649
669
  private handleSectionControllerInitError;
670
+ /**
671
+ * A section that fails to start has no controller of its own to emit its
672
+ * `section-error`, and the host's subscriptions are already off the outgoing
673
+ * section, so the coordinator delivers the error to them while that section
674
+ * is still the one requested.
675
+ */
676
+ private deliverSectionStartError;
650
677
  disposeSectionController(args: {
651
678
  sectionId: string;
652
679
  attemptId?: string;
@@ -666,78 +693,79 @@ export declare class ToolkitCoordinator {
666
693
  private disposeOwnedResources;
667
694
  private waitForAdmittedInitialization;
668
695
  /**
669
- * Initialize TTS service with provider
696
+ * Initialize the TTS service from the `textToSpeech` tool config.
670
697
  */
671
- ensureTTSReady(config?: TTSToolConfig): Promise<void>;
698
+ ensureTTSReady(): Promise<void>;
672
699
  private waitForPendingTTSReconfigure;
673
700
  private _initializeTTS;
674
701
  private resolveTTSToolConfig;
675
702
  private initializeTTSService;
676
- private ensureBrowserVoicesReady;
703
+ waitUntilReady(): Promise<void>;
704
+ isReady(): boolean;
677
705
  /**
678
- * Get all services as a bundle for section player convenience.
679
- * Section player can extract and pass services to child components.
706
+ * Readiness waits for text-to-speech when it is enabled and either starts
707
+ * eagerly or is granted: a granted read-aloud fails before the learner starts.
680
708
  */
681
- getServiceBundle(): ToolkitServiceBundle;
709
+ private ttsRequiredForReadiness;
682
710
  /**
683
- * Get a tool provider from the registry
684
- *
685
- * @param providerId Provider identifier
686
- * @returns Tool provider instance
711
+ * Starts text-to-speech for readiness. A failure policy does not grant leaves
712
+ * the tool degraded, reporting itself unavailable, and readiness settles; a
713
+ * granted tool's failure rejects.
687
714
  */
688
- getToolProvider(providerId: string): Promise<ToolProviderApi<any, any>>;
689
- waitUntilReady(): Promise<void>;
690
- isReady(): boolean;
691
- getInitStatus(): ToolkitInitStatus;
715
+ private startTTSForReadiness;
692
716
  private getTTSConfigFromProviders;
693
717
  private assertCanonicalToolId;
694
718
  private installToolContextResolvers;
695
- setToolContextResolvers(resolvers: ToolContextResolverMap | null | undefined): void;
696
- private notifyToolContextResolverChange;
697
719
  /**
698
- * Check if a tool is enabled.
699
- * Tools are enabled by default unless explicitly disabled.
700
- *
701
- * @param toolId Tool identifier (e.g., 'textToSpeech', 'answerEliminator')
702
- * @returns True if tool is enabled
720
+ * Replace all host-owned render-context resolvers. The toolkit element
721
+ * calls this from `runtime.toolContextResolvers`; it is not on
722
+ * `ToolkitCoordinatorApi`.
703
723
  */
704
- isToolEnabled(toolId: string): boolean;
724
+ setToolContextResolvers(resolvers: ToolContextResolverMap | null | undefined): void;
725
+ private notifyToolContextResolverChange;
705
726
  /**
706
- * Get tool configuration.
707
- *
708
- * @param toolId Tool identifier
709
- * @returns Tool configuration or null if not configured
727
+ * Get tool configuration, or null if the tool is not configured.
710
728
  */
711
- getToolConfig(toolId: "textToSpeech"): TTSToolConfig | null;
729
+ getToolConfig(toolId: "textToSpeech"): TextToSpeechToolProviderConfig | null;
712
730
  getToolConfig(toolId: string): ToolProviderConfig | null;
713
731
  /**
714
- * Update tool configuration.
715
- * Applies changes to underlying services.
716
- *
717
- * @param toolId Tool identifier
718
- * @param updates Partial configuration updates
732
+ * Update tool configuration and apply the change to the underlying services.
719
733
  */
720
- updateToolConfig(toolId: "textToSpeech", updates: Partial<TTSToolConfig>): void;
734
+ updateToolConfig(toolId: "textToSpeech", updates: Partial<TextToSpeechToolProviderConfig>): void;
721
735
  updateToolConfig(toolId: string, updates: Partial<ToolProviderConfig>): void;
722
736
  /**
723
- * Update the enabled tool list for one placement level.
737
+ * Patch one or more placement levels in the canonical tools config.
724
738
  *
725
739
  * This is the generic placement companion to {@link updateToolConfig}:
726
740
  * it validates the next canonical tools config, keeps the policy
727
741
  * engine in lockstep, and emits the same policy-change event used by
728
742
  * live toolbars/debug panels.
729
743
  */
730
- updateToolPlacement(level: ToolPlacementLevel, toolIds: string[]): void;
731
- /**
732
- * Patch one or more placement levels in the canonical tools config.
733
- */
734
744
  updateToolsPlacement(partial: ToolPlacementConfig): void;
735
745
  /**
736
746
  * Resolve the visible tool set for a given placement level + scope.
737
747
  *
738
- * Thin shim over the owned tool-policy engine.
748
+ * Delegates to the owned tool-policy engine and logs the decision's
749
+ * diagnostics through {@link warnPolicyDiagnostics}.
739
750
  */
740
751
  decideToolPolicy(request: ToolPolicyDecisionRequest): ToolPolicyDecision;
752
+ /**
753
+ * Report each policy diagnostic as a console warning and to the
754
+ * {@link onPolicyDiagnostic} listeners, once per code and tool id, and per
755
+ * item for `tool-policy.itemSettingNotApplied`. Every toolbar and feature
756
+ * asks for decisions, so a conflict would otherwise repeat on each; the
757
+ * engine's input diagnostics arrive with each policy change.
758
+ */
759
+ private warnPolicyDiagnostics;
760
+ private notifyPolicyDiagnosticListener;
761
+ /**
762
+ * File a mounted item's policy settings (`requiredTools`, `restrictedTools`,
763
+ * `toolParameters`) under its canonical id. They govern the decisions scoped
764
+ * to that item: its own item-level toolbar, and the feature decisions its
765
+ * content asks with the item's scope. `pie-item-scope` registers them from
766
+ * its `settings` property; the returned function withdraws them.
767
+ */
768
+ registerItemSettings(itemId: string, settings: ItemSettings): () => void;
741
769
  /**
742
770
  * Resolve eligibility for one PNP/AfA feature id, independent of toolbar
743
771
  * placement.
@@ -747,8 +775,8 @@ export declare class ToolkitCoordinator {
747
775
  * `pnpEnforcement` is not consulted.
748
776
  *
749
777
  * Reports once per coordinator when it is asked about a feature with no
750
- * assessment bound. A host in that state gets a correct denial for every
751
- * capability it asks about, which is indistinguishable from a student who was
778
+ * assessment bound. A host in that state gets a denial for every capability
779
+ * no item requires, which is indistinguishable from a student who was
752
780
  * properly declined — so without this, forgetting {@link updateAssessment}
753
781
  * presents as an accommodation that silently never appears.
754
782
  *
@@ -756,14 +784,18 @@ export declare class ToolkitCoordinator {
756
784
  * enforcement is explicitly `"on"`. Its toolkit binds whatever assessment the
757
785
  * host gave, usually none, and a host that passes no profile and leaves
758
786
  * enforcement unset or `"off"` has asked for no accommodation.
787
+ *
788
+ * `scope` is the surface asking; an item's scope brings in that item's
789
+ * registered settings ({@link registerItemSettings}).
759
790
  */
760
- decideFeaturePolicy(featureId: string): FeaturePolicyDecision;
791
+ decideFeaturePolicy<K extends string>(featureId: K, scope?: ToolScope): FeaturePolicyDecision<ToolParametersFor<K>>;
761
792
  /**
762
793
  * Subscribe to policy-engine change events. Fires whenever the
763
794
  * coordinator's bound inputs change (`updateToolConfig`,
764
- * `updateToolPlacement`, `updateAssessment`, `updateCurrentItemRef`,
765
- * `setPnpEnforcement`) or a custom `PolicySource` is registered /
766
- * removed via {@link registerPolicySource}.
795
+ * `updateToolsPlacement`, `updateAssessment`, `setPnpEnforcement`), an
796
+ * item's settings are registered or withdrawn ({@link registerItemSettings}),
797
+ * or a custom `PolicySource` is registered / removed via
798
+ * {@link registerPolicySource}.
767
799
  *
768
800
  * The listener receives a `ToolPolicyChangeEvent` with the event
769
801
  * `reason` and a frozen snapshot of the engine inputs. Listeners
@@ -775,6 +807,7 @@ export declare class ToolkitCoordinator {
775
807
  * their own lifetime ends before the coordinator's.
776
808
  */
777
809
  onPolicyChange(listener: ToolPolicyChangeListener): () => void;
810
+ onPolicyDiagnostic(listener: (diagnostic: ToolPolicyDiagnostic) => void): () => void;
778
811
  /**
779
812
  * Subscribe to accessibility-catalog registrations and removals.
780
813
  *
@@ -789,31 +822,21 @@ export declare class ToolkitCoordinator {
789
822
  /**
790
823
  * Bind (or clear) the active assessment for PNP/profile policy decisions.
791
824
  *
792
- * Under auto-mode (no host override via {@link setPnpEnforcement}),
793
- * the coordinator promotes the engine to `pnpEnforcement: "on"`
794
- * iff the assessment carries any profile precedence material
795
- * (`personalNeedsProfile`, `settings.districtPolicy`,
796
- * `settings.testAdministration`) or the currently-bound item ref
797
- * carries item-level profile policy inputs. A bare assessment record (just
825
+ * Under auto-mode (no host override via {@link setPnpEnforcement}), a
826
+ * decision enforces PNP/profile policy iff the assessment carries profile
827
+ * precedence material (`personalNeedsProfile`, `settings.districtPolicy`,
828
+ * `settings.testAdministration`), or the decision is scoped to an item whose
829
+ * settings carry item-level policy inputs. A bare assessment record (just
798
830
  * `id` / `name`, no PNP, no settings) keeps `"off"`.
799
831
  *
800
832
  * The host override set via {@link setPnpEnforcement} is sticky
801
- * across assessment swaps; calling with `null` clears the binding
802
- * and re-runs the auto-mode helper.
833
+ * across assessment swaps.
803
834
  */
804
835
  updateAssessment(assessment: AssessmentEntity | null): void;
805
836
  /**
806
- * Bind (or clear) the current item reference for policy decisions.
807
- *
808
- * Used by item-level profile gates (item `requiredTools` /
809
- * `restrictedTools` / `toolParameters`). Item-level profile material
810
- * also feeds {@link resolveEffectivePnpEnforcement} — navigating
811
- * to an item with profile settings can flip auto-mode to `"on"` even
812
- * when the parent assessment carries no profile block of its own.
813
- */
814
- updateCurrentItemRef(itemRef: AssessmentItemRef | null): void;
815
- /**
816
- * Override the auto-mode PNP/profile enforcement decision.
837
+ * Override the auto-mode PNP/profile enforcement decision; `null` returns
838
+ * to auto-mode. `"on"` and `"off"` stick across assessment swaps until
839
+ * cleared.
817
840
  */
818
841
  setPnpEnforcement(mode: PnpEnforcementMode | null): void;
819
842
  /**
@@ -834,19 +857,10 @@ export declare class ToolkitCoordinator {
834
857
  * compose with the built-in PNP policy source).
835
858
  */
836
859
  registerPolicySource(source: PolicySource): () => void;
837
- /**
838
- * Register a host-owned resolver for one tool's render context.
839
- *
840
- * Resolvers are evaluated only for tools that already survived the
841
- * framework policy pipeline. They can hide the tool for the current
842
- * scope or attach render params consumed by the packaged registration;
843
- * they cannot re-enable tools blocked by placement, provider config,
844
- * host policy, or PNP/profile rules.
845
- */
846
- registerToolContextResolver(toolId: string, resolver: ToolContextResolver): () => void;
847
860
  hasToolContextResolver(toolId: string): boolean;
848
861
  resolveToolContext(context: ToolContextResolverContext): ResolvedToolContext | null;
849
862
  onToolContextResolverChange(listener: () => void): () => void;
863
+ getToolRegistry(): ToolRegistry;
850
864
  /**
851
865
  * Claim requests for one placement level. Called by a toolbar on mount.
852
866
  */
@@ -865,37 +879,19 @@ export declare class ToolkitCoordinator {
865
879
  * surface, and a host that swapped the registry for one without the tool would
866
880
  * otherwise lose the whole surface to an exception over an absent action.
867
881
  */
868
- canRequestTool(toolId: string, level?: ToolOpenRequest["level"]): boolean;
882
+ canRequestTool(toolId: string, level?: ToolOpenRequest["level"], scopeId?: string): boolean;
869
883
  onToolRequestTargetsChange(listener: () => void): () => void;
870
- /**
871
- * Compute the effective PNP/profile enforcement mode given the explicit
872
- * host override and the auto-mode helper.
873
- *
874
- * Auto-mode (no override) defers to
875
- * {@link resolveDefaultPnpEnforcement}, which returns `"on"`
876
- * exactly when the bound assessment or current item ref carries
877
- * profile precedence material (PNP, district policy, test
878
- * administration, item-level required/restricted/parameters), and
879
- * `"off"` otherwise. Profile gates engage the moment profile material
880
- * is present.
881
- */
882
- private resolveEffectivePnpEnforcement;
883
884
  private resolveConfiguredPnpEnforcement;
884
- /**
885
- * Apply tool configuration changes to underlying services.
886
- * Called after updateToolConfig() with the tool's config before the update.
887
- */
885
+ /** Apply an `updateToolConfig` change to the underlying services. */
888
886
  private _applyToolConfigChange;
889
887
  /**
890
- * Register the provider a tool's updated config names, and unregister the
891
- * one its previous config named when the provider id changed, as
892
- * {@link _reconfigureTTSProvider} does for `tts`. Registration completes
893
- * before this returns, so a check on the policy change the update dispatched
894
- * finds the new provider.
888
+ * Register the provider a tool's updated config builds, replacing the one
889
+ * registered under the tool's id. Registration completes before this returns,
890
+ * so a check on the policy change the update dispatched finds the new provider.
895
891
  */
896
892
  private _registerChangedToolProvider;
897
893
  /**
898
- * Re-register the `tts` provider for the current config and registry, then
894
+ * Re-register the text-to-speech provider for the current config and registry, then
899
895
  * re-initialize unless initialization is lazy. An initialization already
900
896
  * running finishes first: it would otherwise mark its provider ready after
901
897
  * the reset.