@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
@@ -8,48 +8,28 @@
8
8
  * Part of PIE Assessment Toolkit.
9
9
  */
10
10
  import type { I18nServiceApi } from "@pie-players/pie-players-shared/i18n";
11
- import type { AccessibilityCatalog } from "@pie-players/pie-players-shared/types";
12
- import type { AccessibilityCatalogResolver, CatalogChangeListener, CatalogLookupContext, CatalogLookupOptions, CatalogOwnerRegistration, CatalogOwnerView, CatalogStatistics, CatalogType, ResolvedCatalog } from "./AccessibilityCatalogResolver.js";
11
+ import type { AccessibilityCatalog, SectionControllerSessionState } from "@pie-players/pie-players-shared/types";
12
+ import type { CatalogChangeListener, CatalogLookupContext, CatalogLookupOptions, CatalogOwnerRegistration, CatalogOwnerView, CatalogStatistics, CatalogType, ResolvedCatalog } from "./AccessibilityCatalogResolver.js";
13
13
  import type { CatalogOwnerContext } from "./catalog-owner.js";
14
14
  import type { FrameworkErrorListener } from "./framework-error-bus.js";
15
15
  import type { FrameworkErrorModel } from "./framework-error.js";
16
- import type { HighlightColor, HighlightType } from "./HighlightCoordinator.js";
17
- import type { SectionControllerHandle, SectionItemEventSubscriptionArgs, SectionScopedEventSubscriptionArgs, SectionEventSubscriptionArgs, ToolkitCoordinatorHooks, ToolkitInitStatus, TTSToolConfig } from "./ToolkitCoordinator.js";
18
- import type { ThemeConfig } from "./ThemeProvider.js";
16
+ import type { ToolFailurePhase } from "./tool-failure.js";
17
+ import type { Annotation, HighlightColor } from "./HighlightCoordinator.js";
18
+ import type { SerializedRange } from "./RangeSerializer.js";
19
+ import type { SectionControllerHandle, SectionItemEventSubscriptionArgs, SectionScopedEventSubscriptionArgs, SectionEventSubscriptionArgs, ToolkitCoordinatorHooks } from "./ToolkitCoordinator.js";
20
+ import type { ElementIdComponents } from "./ElementToolStateStore.js";
19
21
  import type { ZIndexLayer } from "./ToolCoordinator.js";
20
- import type { PlaybackState, TTSConfig } from "./TTSService.js";
22
+ import type { PlaybackState } from "./TTSService.js";
21
23
  import type { TTSHighlightTargetResolverProvider } from "./tts/highlight-target-resolver.js";
22
- import type { ToolPlacementConfig, ToolPlacementLevel, ToolProviderConfig } from "./tools-config-normalizer.js";
24
+ import type { TextToSpeechToolProviderConfig, ToolPlacementConfig, ToolProviderConfig } from "./tools-config-normalizer.js";
25
+ import type { ToolProviderApi } from "./tool-providers/ToolProviderApi.js";
23
26
  import type { ToolProviderRegistry } from "./tool-providers/ToolProviderRegistry.js";
24
- import type { FeaturePolicyDecision, PolicySource, PnpEnforcementMode, ResolvedEngineInputs, ToolPolicyChangeListener, ToolPolicyDecision, ToolPolicyDecisionRequest } from "../policy/engine.js";
25
- import type { AssessmentEntity, AssessmentItemRef } from "@pie-players/pie-players-shared/types";
26
- import type { ITTSProvider, TTSProviderCapabilities } from "@pie-players/pie-tts";
27
- import type { ResolvedToolContext, ToolContextResolver, ToolContextResolverContext, ToolContextResolverMap } from "./ToolRegistry.js";
27
+ import type { FeaturePolicyDecision, PolicySource, PnpEnforcementMode, ResolvedEngineInputs, ToolPolicyChangeListener, ToolPolicyDecision, ToolPolicyDecisionRequest, ToolPolicyDiagnostic, ToolScope } from "../policy/engine.js";
28
+ import type { AssessmentEntity, ItemSettings, ToolParametersFor } from "@pie-players/pie-players-shared/types";
29
+ import type { TTSConfig } from "@pie-players/pie-tts";
30
+ import type { ResolvedToolContext, ToolContextResolverContext, ToolRegistry } from "./ToolRegistry.js";
28
31
  import type { ToolOpenRequest, ToolRequestTarget } from "./tool-request.js";
29
32
  export type { I18nServiceApi };
30
- /**
31
- * Theme provider interface
32
- *
33
- * Applies consistent accessibility theming across items and tools.
34
- */
35
- export interface ThemeProviderApi {
36
- /**
37
- * Apply theme configuration
38
- */
39
- applyTheme(config: ThemeConfig): void;
40
- /**
41
- * Get current theme configuration
42
- */
43
- getCurrentTheme(): Required<ThemeConfig>;
44
- /**
45
- * Reset to default theme
46
- */
47
- reset(): void;
48
- /**
49
- * Clean up and remove theme styles
50
- */
51
- destroy(): void;
52
- }
53
33
  /**
54
34
  * Highlight coordinator interface
55
35
  *
@@ -57,13 +37,11 @@ export interface ThemeProviderApi {
57
37
  */
58
38
  export interface HighlightCoordinatorApi {
59
39
  /**
60
- * Highlight a text range
61
- */
62
- highlightRange(range: Range, type: HighlightType, color: HighlightColor): void;
63
- /**
64
- * Highlight a word for TTS (temporary)
40
+ * Highlight the word being read (temporary): one range per tree the word
41
+ * spans, all painted, so a word split across inline elements highlights
42
+ * whole.
65
43
  */
66
- highlightTTSWord(textNode: Text, startOffset: number, endOffset: number): void;
44
+ highlightTTSWord(ranges: Range[]): void;
67
45
  /**
68
46
  * Highlight a single element as the active TTS word (temporary).
69
47
  *
@@ -73,40 +51,64 @@ export interface HighlightCoordinatorApi {
73
51
  * (e.g. `<mjx-mi><mjx-c/></mjx-mi>`) and whole-expression fallbacks. Painting
74
52
  * the element itself is what lets a resolved math token highlight as a token
75
53
  * rather than escalating to the full `<math>` / `<mjx-container>`.
76
- *
77
- * Optional so lightweight coordinator mocks can omit it.
78
54
  */
79
- highlightTTSWordElement?(element: Element): void;
55
+ highlightTTSWordElement(element: Element): void;
80
56
  /**
81
57
  * Highlight sentence(s) for TTS (background layer)
82
58
  */
83
59
  highlightTTSSentence(ranges: Range[]): void;
84
60
  /**
85
61
  * Highlight sentence/block element targets for TTS (background layer).
86
- *
87
- * Optional so lightweight coordinator mocks can omit it.
88
62
  */
89
- highlightTTSSentenceElements?(elements: Element[]): void;
63
+ highlightTTSSentenceElements(elements: Element[]): void;
90
64
  /**
91
65
  * Clear all TTS highlights (word and sentence)
92
66
  */
93
67
  clearTTS(): void;
94
68
  /**
95
- * Clear highlights of a specific type
69
+ * Clear the TTS word highlight, keeping the sentence highlight
96
70
  */
97
- clearHighlights(type: HighlightType): void;
71
+ clearTTSWord(): void;
98
72
  /**
99
- * Clear all highlights
73
+ * Record a learner annotation over a range.
74
+ *
75
+ * @returns Annotation id for later lookup or removal
100
76
  */
101
- clearAll(): void;
77
+ addAnnotation(range: Range, color?: HighlightColor): string;
102
78
  /**
103
- * Check if highlighting is supported in current environment
79
+ * Remove one annotation
104
80
  */
105
- isSupported(): boolean;
81
+ removeAnnotation(id: string): void;
106
82
  /**
107
- * Update TTS highlight style dynamically
83
+ * Remove all annotations
108
84
  */
109
- updateTTSHighlightStyle(color: string, opacity: number): void;
85
+ clearAnnotations(): void;
86
+ /**
87
+ * All recorded annotations
88
+ */
89
+ getAnnotations(): Annotation[];
90
+ /**
91
+ * One annotation by id
92
+ */
93
+ getAnnotation(id: string): Annotation | null;
94
+ /**
95
+ * Serialize annotations relative to `root` for persistence
96
+ */
97
+ exportAnnotations(root?: Element): Array<SerializedRange & {
98
+ id: string;
99
+ color: HighlightColor;
100
+ timestamp: number;
101
+ }>;
102
+ /**
103
+ * Restore annotations serialized by `exportAnnotations` against the same root
104
+ *
105
+ * @returns Number of annotations restored
106
+ */
107
+ importAnnotations(data: Array<SerializedRange & {
108
+ id?: string;
109
+ color: HighlightColor;
110
+ timestamp?: number;
111
+ }>, root?: Element): number;
110
112
  }
111
113
  /**
112
114
  * Tool state interface
@@ -118,6 +120,11 @@ export interface ToolState {
118
120
  element: HTMLElement | null;
119
121
  layer: ZIndexLayer;
120
122
  }
123
+ /** Narrows tool-state queries to the instances of one tool. */
124
+ export interface ToolStateFilter {
125
+ /** Base tool id, such as `calculator`, matching every scoped instance of it. */
126
+ baseId?: string;
127
+ }
121
128
  /**
122
129
  * Tool coordinator interface
123
130
  *
@@ -167,14 +174,44 @@ export interface ToolCoordinatorApi {
167
174
  */
168
175
  getToolState(id: string): ToolState | undefined;
169
176
  /**
170
- * Get all visible tools
177
+ * Every visible tool, or with `{ baseId }` every visible instance of one
178
+ * tool, so a host need not parse scoped ids.
171
179
  */
172
- getVisibleTools(): ToolState[];
180
+ getVisibleTools(filter?: ToolStateFilter): ToolState[];
181
+ /**
182
+ * Hide every visible tool, or every instance of one tool with `{ baseId }`.
183
+ */
184
+ hideAllTools(filter?: ToolStateFilter): void;
173
185
  /**
174
186
  * Subscribe to tool state changes
175
187
  */
176
188
  subscribe(listener: () => void): () => void;
177
189
  }
190
+ /** Options for {@link TtsServiceApi.speak}. */
191
+ export interface SpeakOptions {
192
+ /**
193
+ * The spoken card of the content root, read in place of its content when the
194
+ * target holds the whole root.
195
+ */
196
+ catalogId?: string;
197
+ /** The owner whose registered cards apply; without it only assessment-level cards do. */
198
+ catalogContext?: CatalogLookupContext;
199
+ /** BCP 47 language of the content read. */
200
+ language?: string;
201
+ /**
202
+ * For a range target, the content root that scopes highlighting and the
203
+ * offsets of the selection. Defaults to the range's nearest element. An
204
+ * element target is its own root.
205
+ */
206
+ contentRoot?: Element | null;
207
+ /**
208
+ * Who starts the read. The run carries it until the next read starts, a
209
+ * seek's restart included, and {@link TtsServiceApi.getRunOwner} reports it.
210
+ */
211
+ ownerId?: string;
212
+ /** The rate the read starts at; it stays the service's rate afterwards. */
213
+ rate?: number;
214
+ }
178
215
  /**
179
216
  * TTS service interface
180
217
  *
@@ -183,24 +220,13 @@ export interface ToolCoordinatorApi {
183
220
  */
184
221
  export interface TtsServiceApi {
185
222
  /**
186
- * Initialize TTS with a provider
187
- */
188
- initialize(provider: ITTSProvider, config?: Partial<TTSConfig>): Promise<void>;
189
- /**
190
- * Speak text with optional catalog support
223
+ * Read `target` aloud: a range reads the text it selects, an element its
224
+ * content. A node with a spoken card that the target holds whole reads its
225
+ * card, and math reads as math speech. Content marked not-to-be-spoken is
226
+ * never read; when nothing speakable remains, nothing is spoken and playback
227
+ * already running continues.
191
228
  */
192
- speak(text: string, options?: {
193
- catalogId?: string;
194
- catalogContext?: CatalogLookupContext;
195
- language?: string;
196
- contentElement?: Element;
197
- }): Promise<void>;
198
- /**
199
- * Speak a text range
200
- */
201
- speakRange(range: Range, options?: {
202
- contentRoot?: Element | null;
203
- }): Promise<void>;
229
+ speak(target: Range | Element, options?: SpeakOptions): Promise<void>;
204
230
  /**
205
231
  * Pause playback
206
232
  */
@@ -210,16 +236,15 @@ export interface TtsServiceApi {
210
236
  */
211
237
  resume(): void;
212
238
  /**
213
- * Stop playback
239
+ * Stop playback and release the run owner. A read that ends on its own
240
+ * keeps its owner.
214
241
  */
215
242
  stop(): void;
216
243
  /**
217
- * Request active TTS controls to hand off/deactivate their UI state.
218
- *
219
- * This is an orchestration hint for TTS tool chrome and does not replace
220
- * playback controls such as stop/pause/resume.
244
+ * Stop, release the provider and drop every listener and timer. A disposed
245
+ * service cannot speak.
221
246
  */
222
- requestControlHandoff(): void;
247
+ dispose(): void;
223
248
  /**
224
249
  * Seek forward by sentence units
225
250
  */
@@ -228,40 +253,21 @@ export interface TtsServiceApi {
228
253
  * Seek backward by sentence units
229
254
  */
230
255
  seekBackward(units?: number): Promise<void>;
231
- /**
232
- * Check if currently playing
233
- */
234
- isPlaying(): boolean;
235
- /**
236
- * Check if paused
237
- */
238
- isPaused(): boolean;
239
256
  /**
240
257
  * Get current playback state
241
258
  */
242
259
  getState(): PlaybackState;
243
260
  /**
244
- * Get currently speaking text
261
+ * The `ownerId` the latest read started with, or null when it named none,
262
+ * nothing has been read or {@link stop} released it. A new read announces
263
+ * itself through {@link onStateChange} with `loading`, and a stop that
264
+ * releases an owner announces `idle`, so a listener sees the owner change.
245
265
  */
246
- getCurrentText(): string | null;
266
+ getRunOwner(): string | null;
247
267
  /**
248
- * Whether a catalog holds spoken content this service could speak.
249
- * Optional: a service without one resolves a selection to the nearest
250
- * docked catalog id.
268
+ * Subscribe to state changes. Returns the function that unsubscribes.
251
269
  */
252
- hasSpokenAlternate?(catalogId: string, language?: string): boolean;
253
- /**
254
- * Subscribe to state changes
255
- */
256
- onStateChange(id: string, callback: (state: PlaybackState) => void): void;
257
- /**
258
- * Unsubscribe from state changes
259
- */
260
- offStateChange(id: string, callback: (state: PlaybackState) => void): void;
261
- /**
262
- * Get capabilities of current provider
263
- */
264
- getCapabilities(): TTSProviderCapabilities | null;
270
+ onStateChange(callback: (state: PlaybackState) => void): () => void;
265
271
  /**
266
272
  * Update TTS settings dynamically (rate, pitch, voice)
267
273
  */
@@ -270,18 +276,10 @@ export interface TtsServiceApi {
270
276
  * Update playback speed and apply it to active planned playback.
271
277
  */
272
278
  setPlaybackRate(rate: number): Promise<void>;
273
- /**
274
- * Set highlight coordinator for word highlighting
275
- */
276
- setHighlightCoordinator(coordinator: HighlightCoordinatorApi): void;
277
279
  /**
278
280
  * Set a late-bound provider for optional host TTS highlight target remapping.
279
281
  */
280
- setHighlightTargetResolverProvider?(provider: TTSHighlightTargetResolverProvider | null): () => void;
281
- /**
282
- * Set accessibility catalog resolver for spoken content
283
- */
284
- setCatalogResolver(resolver: AccessibilityCatalogResolver): void;
282
+ setHighlightTargetResolverProvider(provider: TTSHighlightTargetResolverProvider | null): () => void;
285
283
  }
286
284
  /**
287
285
  * Accessibility catalog resolver interface
@@ -359,18 +357,15 @@ export interface AccessibilityCatalogResolverApi {
359
357
  */
360
358
  export interface ElementToolStateStoreApi {
361
359
  /**
362
- * Generate a globally unique element ID from components
360
+ * Generate a globally unique element ID from its parts. `attemptId` is `""`
361
+ * when the host names no attempt; a tool keyed by item or section leaves
362
+ * `elementId`, and for a section `itemId`, as `""`.
363
363
  */
364
- getGlobalElementId(assessmentId: string, sectionId: string, itemId: string, elementId: string): string;
364
+ getGlobalElementId(parts: ElementIdComponents): string;
365
365
  /**
366
366
  * Parse a global element ID into its components
367
367
  */
368
- parseGlobalElementId(globalElementId: string): {
369
- assessmentId: string;
370
- sectionId: string;
371
- itemId: string;
372
- elementId: string;
373
- } | null;
368
+ parseGlobalElementId(globalElementId: string): ElementIdComponents | null;
374
369
  /**
375
370
  * Set state for a specific tool on an element
376
371
  */
@@ -408,7 +403,7 @@ export interface ElementToolStateStoreApi {
408
403
  */
409
404
  clearTool(toolId: string): void;
410
405
  /**
411
- * Clear all elements in a specific section
406
+ * Clear all elements in a specific section, across its attempts
412
407
  */
413
408
  clearSection(assessmentId: string, sectionId: string): void;
414
409
  /**
@@ -452,24 +447,16 @@ export interface ToolkitCoordinatorApi {
452
447
  */
453
448
  readonly toolProviderRegistry: ToolProviderRegistry;
454
449
  /**
455
- * Get all services as a bundle
450
+ * Ensure the TTS service is initialized from the `textToSpeech` tool config.
456
451
  */
457
- getServiceBundle(): {
458
- ttsService: TtsServiceApi;
459
- toolCoordinator: ToolCoordinatorApi;
460
- highlightCoordinator: HighlightCoordinatorApi;
461
- elementToolStateStore: ElementToolStateStoreApi;
462
- catalogResolver: AccessibilityCatalogResolverApi;
463
- toolProviderRegistry: ToolProviderRegistry;
464
- };
452
+ ensureTTSReady(): Promise<void>;
465
453
  /**
466
- * Ensure TTS service is initialized and ready.
454
+ * Ensure a tool's provider is initialized and ready. Providers register under
455
+ * their tool's id, so a tool passes its own base tool id. A tool starts its
456
+ * provider here, so that a failure meets the toolkit's tool failure policy:
457
+ * recoverable unless policy grants the tool.
467
458
  */
468
- ensureTTSReady(config?: Record<string, unknown>): Promise<void>;
469
- /**
470
- * Ensure a provider is initialized and ready.
471
- */
472
- ensureProviderReady(providerId: string): Promise<unknown>;
459
+ ensureProviderReady(toolId: string): Promise<ToolProviderApi>;
473
460
  /**
474
461
  * Wait until coordinator initialization is complete.
475
462
  */
@@ -479,27 +466,19 @@ export interface ToolkitCoordinatorApi {
479
466
  */
480
467
  isReady(): boolean;
481
468
  /**
482
- * Read current initialization status.
483
- */
484
- getInitStatus(): ToolkitInitStatus;
485
- /**
486
- * Check if a tool is enabled
469
+ * Subscribe to changes of {@link isReady}.
487
470
  */
488
- isToolEnabled(toolId: string): boolean;
471
+ onReadyChange(listener: () => void): () => void;
489
472
  /**
490
473
  * Get tool configuration
491
474
  */
492
- getToolConfig(toolId: "textToSpeech"): TTSToolConfig | null;
475
+ getToolConfig(toolId: "textToSpeech"): TextToSpeechToolProviderConfig | null;
493
476
  getToolConfig(toolId: string): ToolProviderConfig | null;
494
477
  /**
495
478
  * Update tool configuration
496
479
  */
497
- updateToolConfig(toolId: "textToSpeech", updates: Partial<TTSToolConfig>): void;
480
+ updateToolConfig(toolId: "textToSpeech", updates: Partial<TextToSpeechToolProviderConfig>): void;
498
481
  updateToolConfig(toolId: string, updates: Partial<ToolProviderConfig>): void;
499
- /**
500
- * Update the enabled tool list for one placement level.
501
- */
502
- updateToolPlacement(level: ToolPlacementLevel, toolIds: string[]): void;
503
482
  /**
504
483
  * Patch one or more placement levels in the canonical tools config.
505
484
  */
@@ -526,11 +505,12 @@ export interface ToolkitCoordinatorApi {
526
505
  * aggregate `section-loading-complete`, in the canonical order a
527
506
  * fresh subscriber would have observed.
528
507
  *
529
- * Throws if no active section cohort exists; host code must call
530
- * `getOrCreateSectionController(...)` at least once before
531
- * subscribing. (`toolkit-ready` alone is not sufficient — it fires
532
- * once toolkit state has loaded but before any section controller
533
- * has been created.) The typical pattern is to subscribe once
508
+ * Throws until the first `getOrCreateSectionController(...)` call; a
509
+ * listener added while a section is starting binds when that section
510
+ * becomes active. `runtime-ready` alone is not sufficient: it fires once
511
+ * the coordinator is bound, before any section controller exists. A
512
+ * `<pie-assessment-toolkit>` holding a section emits `toolkit-ready`
513
+ * after its controller resolves. The typical pattern is to subscribe once
534
514
  * immediately after the first `getOrCreateSectionController(...)`
535
515
  * resolves; the subscription then follows the active cohort across
536
516
  * all subsequent navigation without further wiring.
@@ -559,12 +539,18 @@ export interface ToolkitCoordinatorApi {
559
539
  subscribeSectionLifecycleEvents(args: SectionScopedEventSubscriptionArgs): () => void;
560
540
  /**
561
541
  * Create or reuse a section controller with single-flight deduplication.
542
+ *
543
+ * `initialSession` is a host-supplied session. A new controller applies it in
544
+ * replace mode in place of `hydrate()`, before it is published; an existing
545
+ * one applies it unless it equals the current session, keeping recorded
546
+ * responses that a response-free item session would replace.
562
547
  */
563
548
  getOrCreateSectionController(args: {
564
549
  sectionId: string;
565
550
  attemptId?: string;
566
551
  input?: unknown;
567
552
  updateExisting?: boolean;
553
+ initialSession?: SectionControllerSessionState | null;
568
554
  createDefaultController: () => SectionControllerHandle | Promise<SectionControllerHandle>;
569
555
  }): Promise<SectionControllerHandle>;
570
556
  /**
@@ -599,6 +585,12 @@ export interface ToolkitCoordinatorApi {
599
585
  * Optional so structural host coordinators remain assignable.
600
586
  */
601
587
  reportFrameworkError?(model: FrameworkErrorModel): void;
588
+ /**
589
+ * Report that a tool failed in `phase`, under the tool failure policy
590
+ * {@link ToolFailurePhase} describes. Optional so structural host
591
+ * coordinators remain assignable; a reporter without it logs.
592
+ */
593
+ reportToolFailure?(toolId: string, phase: ToolFailurePhase, error: unknown): void;
602
594
  /**
603
595
  * Resolve the visible tool set for a given placement level + scope.
604
596
  * Returns the engine's full decision (visible tools, diagnostics,
@@ -607,24 +599,36 @@ export interface ToolkitCoordinatorApi {
607
599
  */
608
600
  decideToolPolicy(request: ToolPolicyDecisionRequest): ToolPolicyDecision;
609
601
  /**
610
- * Resolve eligibility for one PNP/AfA feature id through the six-level
602
+ * Resolve eligibility for one PNP/AfA feature id through the eight-level
611
603
  * precedence, independent of toolbar placement — for capabilities that
612
604
  * render as their own surface rather than a toolbar button (a signed
613
605
  * alternate's region, for example).
614
606
  *
607
+ * `scope` is the surface asking; an item's scope brings in that item's
608
+ * registered settings ({@link registerItemSettings}).
609
+ *
615
610
  * Optional so host-supplied coordinator stubs predating this method stay
616
611
  * assignable; call sites must feature-detect.
617
612
  */
618
- decideFeaturePolicy?(featureId: string): FeaturePolicyDecision;
613
+ decideFeaturePolicy?<K extends string>(featureId: K, scope?: ToolScope): FeaturePolicyDecision<ToolParametersFor<K>>;
619
614
  /**
620
615
  * Subscribe to policy-engine change events. Fires whenever the
621
616
  * coordinator's bound policy inputs change (`updateToolConfig`,
622
- * `updateToolPlacement`, `updateAssessment`, `updateCurrentItemRef`,
623
- * `setPnpEnforcement`) or a custom `PolicySource` is registered /
624
- * removed. Listeners that need the new visible tool set should
625
- * call `decideToolPolicy(...)` with their level / scope.
617
+ * `updateToolsPlacement`, `updateAssessment`, `setPnpEnforcement`), an
618
+ * item's settings are registered or withdrawn, or a custom `PolicySource`
619
+ * is registered / removed. Listeners that need the new visible tool set
620
+ * should call `decideToolPolicy(...)` with their level / scope.
626
621
  */
627
622
  onPolicyChange(listener: ToolPolicyChangeListener): () => void;
623
+ /**
624
+ * Subscribe to the policy diagnostics the coordinator reports: the ones it
625
+ * logs as console warnings, once per code, tool and item. A new listener is
626
+ * first handed every diagnostic already reported. A change to the bound
627
+ * policy inputs or to PNP enforcement clears the record, and so does a tool
628
+ * registration that makes a named support id known or unknown, so a conflict
629
+ * that survives the change is reported again once.
630
+ */
631
+ onPolicyDiagnostic(listener: (diagnostic: ToolPolicyDiagnostic) => void): () => void;
628
632
  /**
629
633
  * Subscribe to accessibility-catalog registrations and removals.
630
634
  *
@@ -645,30 +649,31 @@ export interface ToolkitCoordinatorApi {
645
649
  /**
646
650
  * Bind (or clear) the active assessment for PNP/profile policy decisions.
647
651
  *
648
- * Under auto-mode (no host override via {@link setPnpEnforcement}),
649
- * the engine flips to `pnpEnforcement: "on"` iff the assessment
650
- * carries profile precedence material (`personalNeedsProfile`,
651
- * `settings.districtPolicy`, `settings.testAdministration`) or the
652
- * currently-bound item ref carries item-level profile inputs. A bare
653
- * assessment record (just `id` / `name`) keeps `"off"`.
652
+ * Under auto-mode (no host override via {@link setPnpEnforcement}), a
653
+ * decision enforces PNP/profile policy iff the assessment carries profile
654
+ * precedence material (`personalNeedsProfile`, `settings.districtPolicy`,
655
+ * `settings.testAdministration`), or the decision is scoped to an item whose
656
+ * registered settings carry item-level policy inputs. A bare assessment
657
+ * record (just `id` / `name`) keeps `"off"`.
654
658
  *
655
659
  * The host override set via {@link setPnpEnforcement} is sticky
656
660
  * across assessment swaps.
657
661
  */
658
662
  updateAssessment(assessment: AssessmentEntity | null): void;
659
663
  /**
660
- * Bind (or clear) the current item reference for policy decisions.
661
- * Used by item-level profile gates (item `requiredTools` /
662
- * `restrictedTools` / `toolParameters`). Item-level profile material
663
- * also feeds the auto-mode helper — navigating to an item with
664
- * profile settings can flip auto-mode to `"on"` even when the parent
665
- * assessment carries no profile block of its own.
664
+ * File a mounted item's policy settings (`requiredTools`, `restrictedTools`,
665
+ * `toolParameters`) under its canonical id; the returned function withdraws
666
+ * them. They govern only decisions scoped to that item: its own item-level
667
+ * toolbar, and feature decisions asked with the item's scope. A section- or
668
+ * assessment-level toolbar ignores them, and reports each tool on it that
669
+ * they restrict or require as `tool-policy.itemSettingNotApplied`.
670
+ * `<pie-item-scope>` registers its `settings` property through this.
666
671
  */
667
- updateCurrentItemRef(itemRef: AssessmentItemRef | null): void;
672
+ registerItemSettings(itemId: string, settings: ItemSettings): () => void;
668
673
  /**
669
674
  * Override the auto-mode PNP/profile enforcement decision. Pass `"on"` /
670
675
  * `"off"` to pin the mode, or `null` to clear the override and
671
- * return to auto-mode (`"on"` iff the bound assessment / item ref
676
+ * return to auto-mode (`"on"` for a decision whose assessment or item
672
677
  * carries profile material, otherwise `"off"`).
673
678
  */
674
679
  setPnpEnforcement(mode: PnpEnforcementMode | null): void;
@@ -683,14 +688,6 @@ export interface ToolkitCoordinatorApi {
683
688
  * (the returned function detaches).
684
689
  */
685
690
  registerPolicySource(source: PolicySource): () => void;
686
- /**
687
- * Register a host-owned resolver for scoped tool render context.
688
- */
689
- registerToolContextResolver(toolId: string, resolver: ToolContextResolver): () => void;
690
- /**
691
- * Replace all host-owned render-context resolvers.
692
- */
693
- setToolContextResolvers(resolvers: ToolContextResolverMap | null | undefined): void;
694
691
  /**
695
692
  * Whether a host resolver is registered for this tool.
696
693
  */
@@ -703,6 +700,14 @@ export interface ToolkitCoordinatorApi {
703
700
  * Subscribe to resolver registration/removal changes.
704
701
  */
705
702
  onToolContextResolverChange(listener: () => void): () => void;
703
+ /**
704
+ * The registry this coordinator's providers and policy resolve against: the
705
+ * one it was built with or adopted, else the empty one it started with. A
706
+ * toolbar that is not handed a registry reads it here, again on each
707
+ * {@link onPolicyChange}, which an adoption fires. Optional for the same reason
708
+ * as the request seam below: a host-supplied coordinator may predate it.
709
+ */
710
+ getToolRegistry?(): ToolRegistry;
706
711
  /**
707
712
  * The tool-open request seam, optional as a group.
708
713
  *
@@ -724,7 +729,7 @@ export interface ToolkitCoordinatorApi {
724
729
  * Whether a request for this tool would reach a toolbar. A surface asks before
725
730
  * offering the affordance.
726
731
  */
727
- canRequestTool?(toolId: string, level?: ToolOpenRequest["level"]): boolean;
732
+ canRequestTool?(toolId: string, level?: ToolOpenRequest["level"], scopeId?: string): boolean;
728
733
  /**
729
734
  * Subscribe to toolbar registration/removal, so a surface can re-evaluate the
730
735
  * actions it offers.
@@ -27,14 +27,14 @@ export interface SectionSessionPersistenceConfig {
27
27
  context: SectionControllerContext;
28
28
  strategy: SectionSessionPersistenceStrategy;
29
29
  }
30
+ /**
31
+ * applySession contract:
32
+ * - Preferred input is the output of getSession().
33
+ * - itemSessions may contain canonical attempt entries
34
+ * ({ itemIdentifier, session, isCompleted }) or raw session payloads
35
+ * ({ id, data, ... }); controller normalizes these before applying.
36
+ */
30
37
  export interface SectionControllerApplySessionOptions {
31
- /**
32
- * applySession contract:
33
- * - Preferred input is the output of getSession().
34
- * - itemSessions may contain canonical attempt entries
35
- * ({ itemIdentifier, session, isCompleted }) or raw session payloads
36
- * ({ id, data, ... }); controller normalizes these before applying.
37
- */
38
38
  mode?: "replace" | "merge";
39
39
  }
40
40
  export interface SectionControllerLoadedRenderable {
@@ -0,0 +1,21 @@
1
+ /**
2
+ * A host-assigned section session, resolved against the session a live
3
+ * controller already holds.
4
+ *
5
+ * The rules are the ones `ItemController.setSession` applies to one item:
6
+ * - a value whose content equals the current session is a no-op, so echoing a
7
+ * snapshot back into the `session` property applies nothing;
8
+ * - an item session with neither a response value nor a response field leaves
9
+ * an item session that holds responses in place. The embedded item player
10
+ * applies the same rule when the section hands the session down, so applying
11
+ * it at section level keeps the controller and its item players from
12
+ * diverging.
13
+ *
14
+ * A controller that holds no session yet takes the value as assigned.
15
+ */
16
+ import type { SectionControllerSessionState } from "@pie-players/pie-players-shared/types";
17
+ /**
18
+ * The session to apply in replace mode, or `null` when applying `next` would
19
+ * change nothing.
20
+ */
21
+ export declare function resolveSectionSessionAssignment(current: SectionControllerSessionState | null | undefined, next: SectionControllerSessionState): SectionControllerSessionState | null;