@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,41 +1,51 @@
1
1
  /**
2
- * Pure transition function for the section runtime engine (M7 — Variant
3
- * C, layered core).
2
+ * Pure transition function for the section runtime engine.
4
3
  *
5
4
  * `transition(state, input)` is total over `(state, input)` pairs and
6
5
  * returns:
7
- * - the next `SectionEngineState` (immutable; the input state object
8
- * is never mutated);
9
- * - the ordered list of `SectionEngineOutput`s the adapter must
10
- * dispatch (DOM events, framework-error fan-out, etc.).
6
+ * - the next `SectionEngineState` (the input state object is never
7
+ * mutated);
8
+ * - the ordered list of `SectionEngineOutput`s the adapter dispatches.
11
9
  *
12
- * The function imports nothing from Svelte, the DOM, or the
13
- * coordinator. The `core/` constraint is enforced by the per-PR audit
14
- * step in the M7 implementation plan.
10
+ * The function imports nothing from Svelte, the DOM, or the coordinator;
11
+ * `scripts/check-engine-core-purity.mjs` enforces that.
15
12
  *
16
13
  * Phase machine (per `engine-state.ts`):
17
14
  * idle → booting-section → engine-ready → interactive → disposed
18
- * (cohort-change rolls back to booting-section for the new cohort
19
- * after emitting `disposed` for the outgoing cohort)
15
+ * booting-section | engine-ready → failed → disposed
16
+ * (cohort-change emits `disposed` for the outgoing cohort and restarts at
17
+ * booting-section for the new one)
18
+ *
19
+ * A readiness update that reports `runtimeError` before `interactive` ends the
20
+ * chain: the first stage the cohort did not reach is recorded as `failed` and
21
+ * any after it as `skipped`, so a host waiting on `engine-ready` or
22
+ * `interactive` always hears an answer.
20
23
  *
21
24
  * Output ordering invariants:
22
25
  * 1. `stage-change` for stage advancement fires before any
23
26
  * `loading-complete` triggered by the same input.
24
27
  * 2. `loading-complete` fires once per cohort, gated on
25
28
  * `state.loadingCompleteEmitted`.
26
- * 3. `framework-error` outputs are independent of the stage chain
27
- * and do not move the phase.
28
- *
29
- * Readiness alias output kinds (`readiness-change`,
30
- * `interaction-ready`, `ready`) and their DOM-event bridge were
31
- * removed in the broad architecture review compat sweep. Hosts that
32
- * need the readiness detail read it via the kernel's `selectReadiness`
33
- * / `getSnapshot` selectors or via `SectionEngineCore.getState()`.
34
29
  */
35
30
  import { cohortsEqual } from "./cohort.js";
36
- import { createReadinessDetail, } from "./engine-readiness.js";
37
- import { phaseToStage } from "./engine-stage-derivation.js";
31
+ import { resolveReadinessGates, } from "./engine-readiness.js";
38
32
  import { createInitialEngineState, } from "./engine-state.js";
33
+ /** `idle` and `failed` have no stage of their own. */
34
+ function phaseToStage(phase) {
35
+ switch (phase) {
36
+ case "idle":
37
+ case "failed":
38
+ return null;
39
+ case "booting-section":
40
+ return "composed";
41
+ case "engine-ready":
42
+ return "engine-ready";
43
+ case "interactive":
44
+ return "interactive";
45
+ case "disposed":
46
+ return "disposed";
47
+ }
48
+ }
39
49
  function emitStageChange(outputs, phase, cohort, status = "entered") {
40
50
  const stage = phaseToStage(phase);
41
51
  if (!stage)
@@ -52,6 +62,7 @@ function startCohort(args) {
52
62
  ...createInitialEngineState(),
53
63
  phase: "booting-section",
54
64
  cohort: args.cohort,
65
+ readinessMode: args.state.readinessMode,
55
66
  effectiveRuntime: args.effectiveRuntime,
56
67
  effectiveToolsConfig: args.effectiveToolsConfig,
57
68
  itemCount: args.itemCount,
@@ -60,46 +71,62 @@ function startCohort(args) {
60
71
  emitStageChange(outputs, "booting-section", args.cohort);
61
72
  return { state: next, outputs };
62
73
  }
74
+ /**
75
+ * End the chain of a cohort that has not reached `interactive`. Returns the
76
+ * `failed` phase after recording the stages it will not reach.
77
+ */
78
+ function failChain(outputs, phase, cohort) {
79
+ if (phase === "booting-section") {
80
+ emitStageChange(outputs, "engine-ready", cohort, "failed");
81
+ emitStageChange(outputs, "interactive", cohort, "skipped");
82
+ }
83
+ else {
84
+ emitStageChange(outputs, "interactive", cohort, "failed");
85
+ }
86
+ return "failed";
87
+ }
63
88
  /**
64
89
  * Apply a readiness update: store new signals, derive the detail in
65
- * the requested mode, advance the phase to `interactive` when gated,
66
- * and emit `loading-complete` once per cohort.
90
+ * the requested mode, end the chain on a runtime error before
91
+ * `interactive`, advance the phase to `interactive` when gated, and emit
92
+ * `loading-complete` once per cohort.
67
93
  */
68
94
  function applyReadinessUpdate(state, args) {
69
95
  if (state.phase === "idle" || state.phase === "disposed") {
70
96
  // No cohort to update; ignore.
71
97
  return { state, outputs: [] };
72
98
  }
73
- const detail = createReadinessDetail({
74
- mode: args.mode,
75
- signals: args.signals,
76
- });
99
+ const detail = resolveReadinessGates(args.mode, args.signals);
77
100
  const outputs = [];
78
101
  let phase = state.phase;
79
102
  let loadingCompleteEmitted = state.loadingCompleteEmitted;
80
- // Stage advancement: engine-ready → interactive when readiness
81
- // satisfies `interactionReady` (mode-aware via `createReadinessDetail`).
82
- if (phase === "engine-ready" && detail.interactionReady) {
103
+ if (args.signals.runtimeError &&
104
+ (phase === "booting-section" || phase === "engine-ready")) {
105
+ phase = failChain(outputs, phase, state.cohort);
106
+ }
107
+ else if (phase === "engine-ready" && detail.interactionReady) {
108
+ // engine-ready → interactive when readiness satisfies
109
+ // `interactionReady` (mode-aware via `resolveReadinessGates`).
83
110
  phase = "interactive";
84
111
  emitStageChange(outputs, phase, state.cohort);
85
112
  }
86
113
  // Canonical `loading-complete` emission. One-shot per cohort, gated
87
- // on the readiness signals indicating every item has finished
88
- // loading.
114
+ // on `allLoadingComplete`: section ready plus the host's loading signal,
115
+ // which the section player kernel raises once the element pre-warm
116
+ // resolves.
89
117
  if (detail.allLoadingComplete && state.cohort && !loadingCompleteEmitted) {
90
118
  loadingCompleteEmitted = true;
91
119
  outputs.push({
92
120
  kind: "loading-complete",
93
121
  cohort: state.cohort,
94
122
  itemCount: args.itemCount,
95
- loadedCount: args.loadedCount,
96
123
  });
97
124
  }
98
125
  const nextState = {
99
126
  ...state,
100
127
  phase,
101
128
  readinessSignals: args.signals,
102
- loadedCount: args.loadedCount,
129
+ readinessMode: args.mode,
103
130
  itemCount: args.itemCount,
104
131
  loadingCompleteEmitted,
105
132
  };
@@ -194,8 +221,8 @@ export function transition(state, input) {
194
221
  }
195
222
  case "section-controller-resolved": {
196
223
  if (state.phase !== "booting-section") {
197
- // Either too early (idle), too late (interactive / disposed),
198
- // or a duplicate notification; the FSM is monotonic.
224
+ // Either too early (idle), too late (interactive / failed /
225
+ // disposed), or a duplicate notification; the FSM is monotonic.
199
226
  return {
200
227
  state: { ...state, controllerResolved: true },
201
228
  outputs: [],
@@ -203,10 +230,20 @@ export function transition(state, input) {
203
230
  }
204
231
  const outputs = [];
205
232
  emitStageChange(outputs, "engine-ready", state.cohort);
233
+ // Readiness can be satisfied before the controller resolves: with
234
+ // preloaded elements the items load in the same flush as the
235
+ // composition. No later signal change would move the cohort on, so
236
+ // the stored snapshot gates `interactive` here.
237
+ let phase = "engine-ready";
238
+ if (resolveReadinessGates(state.readinessMode, state.readinessSignals)
239
+ .interactionReady) {
240
+ phase = "interactive";
241
+ emitStageChange(outputs, phase, state.cohort);
242
+ }
206
243
  return {
207
244
  state: {
208
245
  ...state,
209
- phase: "engine-ready",
246
+ phase,
210
247
  controllerResolved: true,
211
248
  },
212
249
  outputs,
@@ -216,25 +253,9 @@ export function transition(state, input) {
216
253
  return applyReadinessUpdate(state, {
217
254
  signals: input.signals,
218
255
  mode: input.mode,
219
- loadedCount: input.loadedCount,
220
256
  itemCount: input.itemCount,
221
257
  });
222
258
  }
223
- case "framework-error": {
224
- return {
225
- state: {
226
- ...state,
227
- lastFrameworkError: input.error,
228
- readinessSignals: {
229
- ...state.readinessSignals,
230
- runtimeError: input.error.recoverable === true
231
- ? state.readinessSignals.runtimeError
232
- : true,
233
- },
234
- },
235
- outputs: [{ kind: "framework-error", error: input.error }],
236
- };
237
- }
238
259
  case "dispose": {
239
260
  if (state.phase === "disposed") {
240
261
  return { state, outputs: [] };
@@ -1,23 +1,20 @@
1
1
  /**
2
- * Section runtime engine — facade entry point (M7 — Variant C).
2
+ * Section runtime engine — the stable entry for a host that drives a section's
3
+ * stage chain.
3
4
  *
4
- * Narrow, stable public surface for hosts that want to mount, drive,
5
- * or dispose a section runtime via the layered engine. Re-exports the
6
- * `SectionRuntimeEngine` facade and its `attachHost` arg shape.
7
- *
8
- * **Pairing.** This module is the stable counterpart to
9
- * `./runtime/internal`, which exposes the wider, evolving surface
10
- * (core types, adapter bridges, cohort helpers) for advanced hosts and
11
- * for the engine's own tests / benchmarks. Consumers that only need to
12
- * mount + drive a section runtime should import from here. Consumers
13
- * that need to reach past the facade (e.g. construct an adapter
14
- * manually, inspect FSM state types, build alternate fan-out paths)
15
- * should import from `./runtime/internal` and accept the documented
16
- * stability disclaimer there.
17
- *
18
- * The package's `exports` map adds `./runtime/engine` in M7 PR 3
19
- * alongside the facade refactor.
5
+ * Besides the `SectionRuntimeEngine` facade it carries the vocabulary of the
6
+ * facade's own surface: the inputs `dispatchInput` takes and the outputs
7
+ * `subscribe` delivers, the state `getState` returns, the runtime config and its
8
+ * resolution, the id a section runs under, the cohort an `initialize` or
9
+ * `cohort-change` input names, and the
10
+ * readiness signals. The section player's layout kernel is the host
11
+ * this was cut for. The engine's core, adapter and bridges stay behind the
12
+ * facade, with no entry of their own.
20
13
  */
21
14
  export { SectionRuntimeEngine, type SectionRuntimeEngineHostArgs, } from "./SectionRuntimeEngine.js";
22
- export { SECTION_RUNTIME_ENGINE_KEY, type SectionRuntimeEngineContext, } from "./engine-context.js";
23
- export { sectionRuntimeEngineHostContext, connectSectionRuntimeEngineHostContext, type SectionRuntimeLifecycleHandle, type SectionRuntimeEngineHostContextValue, type SectionRuntimeEngineHostContextListener, } from "./section-runtime-engine-host-context.js";
15
+ export type { SectionEngineInput } from "./core/engine-input.js";
16
+ export type { SectionEngineOutput } from "./core/engine-output.js";
17
+ export type { SectionEnginePhase, SectionEngineState, } from "./core/engine-state.js";
18
+ export { DEFAULT_ENV, DEFAULT_ISOLATION, DEFAULT_PLAYER_TYPE, resolveSectionEngineRuntimeState, resolveSectionId, type FrameworkErrorHandler, type LoadingCompleteHandler, type PlayerOverrides, type RuntimeConfig, type RuntimeInputs, type StageChangeHandler, } from "./core/engine-resolver.js";
19
+ export { cohortsEqual, makeCohort, type CohortKey } from "./core/cohort.js";
20
+ export type { EngineReadinessSignals } from "./core/engine-readiness.js";
@@ -1,23 +1,16 @@
1
1
  /**
2
- * Section runtime engine — facade entry point (M7 — Variant C).
2
+ * Section runtime engine — the stable entry for a host that drives a section's
3
+ * stage chain.
3
4
  *
4
- * Narrow, stable public surface for hosts that want to mount, drive,
5
- * or dispose a section runtime via the layered engine. Re-exports the
6
- * `SectionRuntimeEngine` facade and its `attachHost` arg shape.
7
- *
8
- * **Pairing.** This module is the stable counterpart to
9
- * `./runtime/internal`, which exposes the wider, evolving surface
10
- * (core types, adapter bridges, cohort helpers) for advanced hosts and
11
- * for the engine's own tests / benchmarks. Consumers that only need to
12
- * mount + drive a section runtime should import from here. Consumers
13
- * that need to reach past the facade (e.g. construct an adapter
14
- * manually, inspect FSM state types, build alternate fan-out paths)
15
- * should import from `./runtime/internal` and accept the documented
16
- * stability disclaimer there.
17
- *
18
- * The package's `exports` map adds `./runtime/engine` in M7 PR 3
19
- * alongside the facade refactor.
5
+ * Besides the `SectionRuntimeEngine` facade it carries the vocabulary of the
6
+ * facade's own surface: the inputs `dispatchInput` takes and the outputs
7
+ * `subscribe` delivers, the state `getState` returns, the runtime config and its
8
+ * resolution, the id a section runs under, the cohort an `initialize` or
9
+ * `cohort-change` input names, and the
10
+ * readiness signals. The section player's layout kernel is the host
11
+ * this was cut for. The engine's core, adapter and bridges stay behind the
12
+ * facade, with no entry of their own.
20
13
  */
21
14
  export { SectionRuntimeEngine, } from "./SectionRuntimeEngine.js";
22
- export { SECTION_RUNTIME_ENGINE_KEY, } from "./engine-context.js";
23
- export { sectionRuntimeEngineHostContext, connectSectionRuntimeEngineHostContext, } from "./section-runtime-engine-host-context.js";
15
+ export { DEFAULT_ENV, DEFAULT_ISOLATION, DEFAULT_PLAYER_TYPE, resolveSectionEngineRuntimeState, resolveSectionId, } from "./core/engine-resolver.js";
16
+ export { cohortsEqual, makeCohort } from "./core/cohort.js";
@@ -0,0 +1,13 @@
1
+ /**
2
+ * How long a warning about a missing input waits when a host may still be
3
+ * supplying it, such as a toolkit or a registry loaded after mount.
4
+ */
5
+ export declare const PENDING_INPUT_WARNING_DELAY_MS = 10000;
6
+ /**
7
+ * Warns about a setup mistake once per document, across every copy of the
8
+ * toolkit loaded into it: the latch is a `Symbol.for` slot on the document, so
9
+ * the custom-element bundle and the modules a host imports share it. Not
10
+ * development-only, because the custom-element build compiles those branches
11
+ * out, and a host misconfigures in production as readily as anywhere.
12
+ */
13
+ export declare function warnOncePerDocument(doc: Document | null | undefined, key: string, message: string): void;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * How long a warning about a missing input waits when a host may still be
3
+ * supplying it, such as a toolkit or a registry loaded after mount.
4
+ */
5
+ export const PENDING_INPUT_WARNING_DELAY_MS = 10_000;
6
+ /**
7
+ * Warns about a setup mistake once per document, across every copy of the
8
+ * toolkit loaded into it: the latch is a `Symbol.for` slot on the document, so
9
+ * the custom-element bundle and the modules a host imports share it. Not
10
+ * development-only, because the custom-element build compiles those branches
11
+ * out, and a host misconfigures in production as readily as anywhere.
12
+ */
13
+ export function warnOncePerDocument(doc, key, message) {
14
+ if (!doc)
15
+ return;
16
+ const slot = Symbol.for(`pie.assessmentToolkit.warned.${key}`);
17
+ const latches = doc;
18
+ if (latches[slot])
19
+ return;
20
+ latches[slot] = true;
21
+ console.warn(message);
22
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Which policy inputs `<pie-assessment-toolkit>` forwards to the coordinator it
3
+ * owns.
4
+ *
5
+ * The toolkit forwards an input when its own value for it changes. A host
6
+ * driving the owned coordinator directly — an embedded toolkit's host binds its
7
+ * assessment from `runtime-ready` or `toolkit-ready` — keeps that binding until
8
+ * the toolkit's own value changes, so an unrelated re-run of the forwarding
9
+ * effect (a `tools` change, a coordinator rebuild trigger) cannot reset it. A
10
+ * coordinator not forwarded to yet is newly built and holds no inputs, so it
11
+ * receives only the inputs that are set.
12
+ */
13
+ import type { AssessmentEntity } from "@pie-players/pie-players-shared/types";
14
+ import type { PnpEnforcementMode } from "../policy/core/ToolPolicyEngine.js";
15
+ export interface ForwardedPolicyInputs {
16
+ pnpEnforcement: PnpEnforcementMode | null;
17
+ assessment: AssessmentEntity | null;
18
+ }
19
+ /**
20
+ * The inputs to forward, in apply order: the enforcement override first, so
21
+ * binding the assessment never resolves auto-mode against a stale override.
22
+ * `previous` is what was last forwarded to the same coordinator, or `null` for
23
+ * a coordinator not forwarded to yet.
24
+ */
25
+ export declare function policyInputsToForward(previous: ForwardedPolicyInputs | null, next: ForwardedPolicyInputs): Array<keyof ForwardedPolicyInputs>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Which policy inputs `<pie-assessment-toolkit>` forwards to the coordinator it
3
+ * owns.
4
+ *
5
+ * The toolkit forwards an input when its own value for it changes. A host
6
+ * driving the owned coordinator directly — an embedded toolkit's host binds its
7
+ * assessment from `runtime-ready` or `toolkit-ready` — keeps that binding until
8
+ * the toolkit's own value changes, so an unrelated re-run of the forwarding
9
+ * effect (a `tools` change, a coordinator rebuild trigger) cannot reset it. A
10
+ * coordinator not forwarded to yet is newly built and holds no inputs, so it
11
+ * receives only the inputs that are set.
12
+ */
13
+ /**
14
+ * The inputs to forward, in apply order: the enforcement override first, so
15
+ * binding the assessment never resolves auto-mode against a stale override.
16
+ * `previous` is what was last forwarded to the same coordinator, or `null` for
17
+ * a coordinator not forwarded to yet.
18
+ */
19
+ export function policyInputsToForward(previous, next) {
20
+ const order = [
21
+ "pnpEnforcement",
22
+ "assessment",
23
+ ];
24
+ return order.filter((key) => previous ? !Object.is(previous[key], next[key]) : next[key] !== null);
25
+ }
@@ -1,4 +1,5 @@
1
1
  import type { SessionCommitReason } from "@pie-players/pie-players-shared/pie";
2
+ import type { ItemSettings } from "@pie-players/pie-players-shared/types";
2
3
  import type { MediaTimeSource } from "@pie-players/pie-players-shared/timed-media";
3
4
  export declare const PIE_REGISTER_EVENT = "pie-register";
4
5
  export declare const PIE_UNREGISTER_EVENT = "pie-unregister";
@@ -15,7 +16,17 @@ export interface RuntimeRegistrationDetail {
15
16
  canonicalItemId?: string;
16
17
  contentKind?: string;
17
18
  item?: unknown;
19
+ /**
20
+ * An item's policy settings, which govern decisions scoped to the item; see
21
+ * `ToolkitCoordinatorApi.registerItemSettings`.
22
+ */
23
+ settings?: ItemSettings;
18
24
  element: HTMLElement;
25
+ /**
26
+ * The runtime the shell found through `assessmentToolkitHostRuntimeContext`.
27
+ * A toolkit claims an event carrying it only when the id is its own.
28
+ */
29
+ runtimeId?: string;
19
30
  }
20
31
  export interface ItemSessionChangedDetail {
21
32
  itemId: string;
@@ -60,16 +71,14 @@ export interface InternalFormativeActionDetail {
60
71
  /**
61
72
  * A Media Time Source becoming available or going away.
62
73
  *
63
- * The one seam through which a timed-media section reaches media, and
64
- * deliberately the *only* one: the stimulus card dispatches this with a native
65
- * `<video>` adapter, and a host wrapping a third-party player dispatches the same
66
- * event with its own port. One code path, two producers — which is what keeps
67
- * "a host can supply its own media element without shipping a PIE element" true
68
- * rather than aspirational.
74
+ * The only seam through which a timed-media section reaches media: the stimulus
75
+ * card dispatches it with a native `<video>` adapter, and a host wrapping a
76
+ * third-party player dispatches it with its own port. One code path with two
77
+ * producers is what lets a host supply its own media element without shipping a
78
+ * PIE element.
69
79
  *
70
- * `source` carries a live object, not serializable data. That is fine and
71
- * intended: this event never crosses a realm, exactly like the element reference
72
- * on `pie-register`.
80
+ * `source` is a live object. The event never crosses a realm, like the element
81
+ * reference on `pie-register`.
73
82
  */
74
83
  export interface InternalMediaTimeSourceDetail {
75
84
  /** The renderable that owns the media, for matching against `stimulusRef`. */
@@ -82,11 +91,10 @@ export interface InternalMediaTimeSourceDetail {
82
91
  * wiring its own player, and omitting the field reads as `"host"` because a
83
92
  * caller constructing this event by hand is one.
84
93
  *
85
- * Load-bearing for precedence: the card re-runs its discovery whenever its
86
- * content changes, so without this a host that supplied a third-party port would
87
- * have it silently replaced by the native element mid-session — and the
88
- * capabilities would flip back with it, which is exactly the "appears to enforce"
89
- * failure this contract exists to prevent.
94
+ * Precedence depends on it: the card re-runs its discovery whenever its content
95
+ * changes, and without the field the native element would replace a host's
96
+ * third-party port mid-session, flipping the capabilities back with it, so a
97
+ * policy would read as enforced while it is not.
90
98
  */
91
99
  origin?: "native-adapter" | "host";
92
100
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether the toolkit running as `runtimeId` claims a shell's event. A shell
3
+ * scope puts the id of the runtime that answered it in `detail.runtimeId`, and
4
+ * only that runtime claims the event. An event without one, from a shell that
5
+ * dispatches on its own, is claimed when `isLocalTarget` resolves its target
6
+ * to this runtime.
7
+ */
8
+ export declare function isRuntimeEventClaimed(event: Event, runtimeId: string, isLocalTarget: (target: EventTarget | null) => boolean): boolean;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Whether the toolkit running as `runtimeId` claims a shell's event. A shell
3
+ * scope puts the id of the runtime that answered it in `detail.runtimeId`, and
4
+ * only that runtime claims the event. An event without one, from a shell that
5
+ * dispatches on its own, is claimed when `isLocalTarget` resolves its target
6
+ * to this runtime.
7
+ */
8
+ export function isRuntimeEventClaimed(event, runtimeId, isLocalTarget) {
9
+ const addressedTo = event
10
+ .detail?.runtimeId;
11
+ if (typeof addressedTo === "string" && addressedTo !== "") {
12
+ return addressedTo === runtimeId;
13
+ }
14
+ return isLocalTarget(event.target);
15
+ }
@@ -2,6 +2,6 @@
2
2
  * Stable runtime-instance id generator.
3
3
  *
4
4
  * Produces a per-runtime id used to scope DOM attribute names and
5
- * telemetry tags. Single export by design — not a "guards" module.
5
+ * telemetry tags.
6
6
  */
7
7
  export declare function createRuntimeId(prefix?: string): string;
@@ -2,7 +2,7 @@
2
2
  * Stable runtime-instance id generator.
3
3
  *
4
4
  * Produces a per-runtime id used to scope DOM attribute names and
5
- * telemetry tags. Single export by design — not a "guards" module.
5
+ * telemetry tags.
6
6
  */
7
7
  export function createRuntimeId(prefix = "runtime") {
8
8
  return `${prefix}-${Math.random().toString(16).slice(2)}-${Date.now()}`;
@@ -0,0 +1,45 @@
1
+ import type { ShellContextKind } from "../context/assessment-toolkit-context.js";
2
+ /**
3
+ * `section`: the shell is its content's only channel to the section. The
4
+ * player's `session-changed`, `load-complete` and `player-error` stop at the
5
+ * shell and travel on as the runtime's internal events, with an item's
6
+ * response changes also announced as `item-session-changed`.
7
+ *
8
+ * `plain`: the host owns the player and listens to it, so the player's events
9
+ * pass through untouched. The runtime still hears that the content loaded or
10
+ * failed, which a section bound later replays; sessions stay with the host.
11
+ */
12
+ export type ShellEventBridgeMode = "section" | "plain";
13
+ export interface ShellEventBridgeIdentity {
14
+ itemId: string;
15
+ canonicalItemId?: string;
16
+ contentKind?: string;
17
+ }
18
+ export interface ShellEventBridgeOptions {
19
+ /** The shell element, where the player's events arrive and leave from. */
20
+ host: HTMLElement;
21
+ kind: ShellContextKind;
22
+ /** Read as each event arrives, so a prop change needs no rebinding. */
23
+ identity: () => ShellEventBridgeIdentity;
24
+ /** Read as each event arrives. */
25
+ mode: () => ShellEventBridgeMode;
26
+ /** Sends an event addressed to the shell's runtime. */
27
+ send: (type: string, detail: object) => void;
28
+ }
29
+ export interface ShellEventBridge {
30
+ /**
31
+ * Gives an item's pending session one last chance to reach the section, then
32
+ * stops listening. The commit runs while the player is still inside the
33
+ * shell, so its `session-changed` arrives at the bridge before it is unbound.
34
+ * The shell has usually left the document by then; `send` delivers the
35
+ * forwarded session on the runtime's element.
36
+ */
37
+ disconnect: () => void;
38
+ }
39
+ /**
40
+ * A shell's translation of its player's events into the runtime's, shared by
41
+ * `<pie-item-scope>` and `<pie-passage-shell>`. The dedupe
42
+ * state lives as long as the bridge, so a prop change does not forget what was
43
+ * forwarded.
44
+ */
45
+ export declare function createShellEventBridge(options: ShellEventBridgeOptions): ShellEventBridge;