@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.
- package/README.md +658 -714
- package/custom-elements.json +1315 -0
- package/dist/attempt/TestSession.d.ts +1 -21
- package/dist/attempt/TestSession.js +16 -102
- package/dist/components/ItemScope.custom-element.d.ts +1 -0
- package/dist/components/ItemScope.custom-element.js +1 -0
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-3zrc4p3d.js +4 -0
- package/dist/components/chunks/ItemToolBar-66hcwmfw.js +2 -0
- package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
- package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
- package/dist/components/chunks/{ItemToolBar-gmrryv2v.js → ItemToolBar-kkj69ptr.js} +1 -1
- package/dist/components/chunks/ItemToolBar-vdkyn9f3.js +2 -0
- package/dist/components/chunks/sre-engine-bj997w4b.js +1 -0
- package/dist/components/item-scope-element.d.ts +2 -0
- package/dist/components/item-scope-element.js +2 -0
- package/dist/context/assessment-toolkit-context.d.ts +33 -6
- package/dist/index.d.ts +25 -50
- package/dist/index.js +15 -45
- package/dist/policy/core/PolicySource.d.ts +2 -2
- package/dist/policy/core/ToolPolicyEngine.d.ts +118 -34
- package/dist/policy/core/ToolPolicyEngine.js +203 -56
- package/dist/policy/core/compose-decision.d.ts +28 -7
- package/dist/policy/core/compose-decision.js +95 -74
- package/dist/policy/core/decision-types.d.ts +98 -55
- package/dist/policy/core/feature-decision.d.ts +28 -19
- package/dist/policy/core/feature-decision.js +15 -11
- package/dist/policy/core/pnp-policy-inputs.d.ts +29 -35
- package/dist/policy/core/pnp-policy-inputs.js +40 -88
- package/dist/policy/core/provenance.d.ts +10 -5
- package/dist/policy/core/provenance.js +1 -1
- package/dist/policy/core/tool-parameters.d.ts +11 -0
- package/dist/policy/core/tool-parameters.js +15 -0
- package/dist/policy/engine.d.ts +7 -23
- package/dist/policy/engine.js +5 -20
- package/dist/policy/sources/PnpPolicySource.d.ts +43 -68
- package/dist/policy/sources/PnpPolicySource.js +133 -132
- package/dist/runtime/SectionControllerBinding.d.ts +283 -0
- package/dist/runtime/SectionControllerBinding.js +456 -0
- package/dist/runtime/SectionRuntimeEngine.d.ts +26 -289
- package/dist/runtime/SectionRuntimeEngine.js +30 -372
- package/dist/runtime/adapter/SectionEngineAdapter.d.ts +19 -80
- package/dist/runtime/adapter/SectionEngineAdapter.js +19 -92
- package/dist/runtime/adapter/dom-event-bridge.d.ts +15 -30
- package/dist/runtime/adapter/dom-event-bridge.js +17 -44
- package/dist/runtime/adapter/subscriber-fanout.d.ts +1 -3
- package/dist/runtime/adapter/subscriber-fanout.js +2 -6
- package/dist/runtime/catalog-context.d.ts +19 -0
- package/dist/runtime/catalog-context.js +28 -0
- package/dist/runtime/composition-emit-scheduler.d.ts +12 -18
- package/dist/runtime/composition-emit-scheduler.js +10 -16
- package/dist/runtime/content-language.d.ts +32 -0
- package/dist/runtime/content-language.js +46 -0
- package/dist/runtime/content-region.d.ts +13 -0
- package/dist/runtime/content-region.js +29 -0
- package/dist/runtime/content-registration.d.ts +13 -0
- package/dist/runtime/content-registration.js +25 -0
- package/dist/runtime/core/SectionEngineCore.d.ts +2 -4
- package/dist/runtime/core/SectionEngineCore.js +2 -6
- package/dist/runtime/core/cohort.d.ts +1 -6
- package/dist/runtime/core/cohort.js +1 -10
- package/dist/runtime/core/engine-input.d.ts +18 -30
- package/dist/runtime/core/engine-input.js +11 -12
- package/dist/runtime/core/engine-output.d.ts +17 -40
- package/dist/runtime/core/engine-output.js +9 -21
- package/dist/runtime/core/engine-readiness.d.ts +5 -37
- package/dist/runtime/core/engine-readiness.js +8 -41
- package/dist/runtime/core/engine-resolver.d.ts +46 -74
- package/dist/runtime/core/engine-resolver.js +18 -43
- package/dist/runtime/core/engine-state.d.ts +28 -36
- package/dist/runtime/core/engine-state.js +18 -21
- package/dist/runtime/core/engine-transition.d.ts +14 -19
- package/dist/runtime/core/engine-transition.js +74 -53
- package/dist/runtime/engine.d.ts +16 -19
- package/dist/runtime/engine.js +12 -19
- package/dist/runtime/page-warnings.d.ts +13 -0
- package/dist/runtime/page-warnings.js +22 -0
- package/dist/runtime/policy-input-forwarding.d.ts +25 -0
- package/dist/runtime/policy-input-forwarding.js +25 -0
- package/dist/runtime/registration-events.d.ts +22 -14
- package/dist/runtime/runtime-event-claim.d.ts +8 -0
- package/dist/runtime/runtime-event-claim.js +15 -0
- package/dist/runtime/runtime-id.d.ts +1 -1
- package/dist/runtime/runtime-id.js +1 -1
- package/dist/runtime/shell-event-bridge.d.ts +45 -0
- package/dist/runtime/shell-event-bridge.js +127 -0
- package/dist/runtime/shell-registration.d.ts +73 -0
- package/dist/runtime/shell-registration.js +95 -0
- package/dist/runtime/shell-scope.d.ts +68 -0
- package/dist/runtime/shell-scope.js +194 -0
- package/dist/runtime/tool-host-contract.d.ts +8 -14
- package/dist/runtime/tool-host-contract.js +12 -12
- package/dist/runtime/unclaimed-registration-watch.d.ts +7 -0
- package/dist/runtime/unclaimed-registration-watch.js +23 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
- package/dist/services/AccessibilityCatalogResolver.js +29 -42
- package/dist/services/ElementToolStateStore.d.ts +42 -67
- package/dist/services/ElementToolStateStore.js +65 -71
- package/dist/services/HighlightCoordinator.d.ts +28 -40
- package/dist/services/HighlightCoordinator.js +459 -381
- package/dist/services/RangeSerializer.d.ts +11 -33
- package/dist/services/RangeSerializer.js +88 -59
- package/dist/services/SSMLExtractor.d.ts +8 -31
- package/dist/services/SSMLExtractor.js +18 -40
- package/dist/services/TTSService.d.ts +159 -119
- package/dist/services/TTSService.js +937 -822
- package/dist/services/ToolCoordinator.d.ts +42 -102
- package/dist/services/ToolCoordinator.js +178 -256
- package/dist/services/ToolRegistry.d.ts +152 -133
- package/dist/services/ToolRegistry.js +192 -178
- package/dist/services/ToolkitCoordinator.d.ts +233 -237
- package/dist/services/ToolkitCoordinator.js +615 -557
- package/dist/services/audio-handoff.d.ts +6 -7
- package/dist/services/audio-handoff.js +20 -14
- package/dist/services/catalog-owner.d.ts +0 -1
- package/dist/services/framework-error-bus.d.ts +3 -6
- package/dist/services/framework-error-bus.js +3 -6
- package/dist/services/framework-error.d.ts +51 -13
- package/dist/services/framework-error.js +19 -20
- package/dist/services/interfaces.d.ts +189 -184
- package/dist/services/section-controller-types.d.ts +7 -7
- package/dist/services/section-session-assignment.d.ts +21 -0
- package/dist/services/section-session-assignment.js +80 -0
- package/dist/services/spoken-audio-cards.d.ts +2 -6
- package/dist/services/spoken-audio-cards.js +2 -6
- package/dist/services/tool-config-defaults.d.ts +3 -3
- package/dist/services/tool-config-defaults.js +3 -3
- package/dist/services/tool-config-validation.d.ts +9 -12
- package/dist/services/tool-config-validation.js +47 -87
- package/dist/services/tool-context.d.ts +7 -31
- package/dist/services/tool-context.js +99 -65
- package/dist/services/tool-failure.d.ts +30 -0
- package/dist/services/tool-failure.js +11 -0
- package/dist/services/tool-icons.d.ts +5 -5
- package/dist/services/tool-icons.js +6 -5
- package/dist/services/tool-instance-id.d.ts +8 -7
- package/dist/services/tool-instance-id.js +12 -24
- package/dist/services/tool-providers/TTSToolProvider.d.ts +20 -58
- package/dist/services/tool-providers/TTSToolProvider.js +32 -85
- package/dist/services/tool-providers/ToolProviderApi.d.ts +10 -11
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +29 -60
- package/dist/services/tool-providers/ToolProviderRegistry.js +128 -144
- package/dist/services/tool-request.d.ts +31 -12
- package/dist/services/tool-request.js +31 -16
- package/dist/services/toolbar-decided-tools.d.ts +16 -0
- package/dist/services/toolbar-decided-tools.js +29 -0
- package/dist/services/toolbar-items.js +2 -5
- package/dist/services/tools-config-normalizer.d.ts +33 -29
- package/dist/services/tools-config-normalizer.js +26 -28
- package/dist/services/tts/browser-provider.d.ts +39 -6
- package/dist/services/tts/browser-provider.js +280 -160
- package/dist/services/tts/catalog-span-alignment.js +14 -7
- package/dist/services/tts/flat-tree.d.ts +64 -0
- package/dist/services/tts/flat-tree.js +269 -0
- package/dist/services/tts/generated-speech/assemble-plan.d.ts +3 -1
- package/dist/services/tts/generated-speech/assemble-plan.js +3 -1
- package/dist/services/tts/generated-speech/dom/build-dom-plan.d.ts +2 -0
- package/dist/services/tts/generated-speech/dom/build-dom-plan.js +1 -1
- package/dist/services/tts/generated-speech/dom/to-chunk-inputs.d.ts +2 -2
- package/dist/services/tts/generated-speech/index.d.ts +1 -1
- package/dist/services/tts/generated-speech/index.js +1 -1
- package/dist/services/tts/generated-speech/math-speech-cache.d.ts +3 -1
- package/dist/services/tts/generated-speech/math-speech-cache.js +5 -1
- package/dist/services/tts/generated-speech/types.d.ts +1 -1
- package/dist/services/tts/generated-speech/types.js +1 -1
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +22 -16
- package/dist/services/tts/highlight-pipeline/prose-boundary-resolver.js +6 -4
- package/dist/services/tts/highlight-pipeline/readable-region.js +3 -2
- package/dist/services/tts/highlight-pipeline/types.d.ts +5 -0
- package/dist/services/tts/highlight-pipeline/visible-map-range.d.ts +12 -0
- package/dist/services/tts/highlight-pipeline/visible-map-range.js +73 -7
- package/dist/services/tts/highlight-target-resolver.d.ts +12 -0
- package/dist/services/tts/math-aware-text-processing.d.ts +5 -1
- package/dist/services/tts/math-aware-text-processing.js +42 -47
- package/dist/services/tts/math-control-names.d.ts +21 -0
- package/dist/services/tts/math-control-names.js +142 -0
- package/dist/services/tts/math-speech.d.ts +12 -1
- package/dist/services/tts/math-speech.js +54 -18
- package/dist/services/tts/mathml-sanitization.d.ts +7 -0
- package/dist/services/tts/mathml-sanitization.js +9 -1
- package/dist/services/tts/provider-options.d.ts +52 -0
- package/dist/services/tts/provider-options.js +1 -0
- package/dist/services/tts/ssml/spoken-text.d.ts +2 -26
- package/dist/services/tts/ssml/spoken-text.js +29 -0
- package/dist/services/tts/start-failure.d.ts +4 -0
- package/dist/services/tts/start-failure.js +19 -0
- package/dist/services/tts/text-processing.d.ts +9 -0
- package/dist/services/tts/text-processing.js +46 -33
- package/dist/services/tts/text-segmentation.d.ts +12 -0
- package/dist/services/tts/text-segmentation.js +60 -10
- package/dist/services/tts-runtime-config.d.ts +54 -26
- package/dist/services/tts-runtime-config.js +27 -112
- package/dist/tools/content-capability-resolution.d.ts +9 -11
- package/dist/tools/content-capability-resolution.js +8 -45
- package/dist/tools/registration.d.ts +59 -0
- package/dist/tools/registration.js +55 -0
- package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
- package/dist/tools/registrations/toolbar-registration-helpers.js +8 -2
- package/dist/tools/tool-surface-host.d.ts +6 -10
- package/dist/tools/tool-surface-host.js +45 -50
- package/dist/tools/tool-tag-map.d.ts +5 -15
- package/dist/tools/tool-tag-map.js +6 -20
- package/dist/utils/structural-equality.d.ts +11 -0
- package/dist/utils/structural-equality.js +47 -0
- package/package.json +15 -29
- package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts +0 -49
- package/dist/attempt/adapters/activity-to-test-attempt-session.js +0 -138
- package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +0 -40
- package/dist/components/chunks/ItemToolBar-h4xap0t0.js +0 -4
- package/dist/components/chunks/ItemToolBar-wr2myaah.js +0 -2
- package/dist/components/chunks/sre-engine-wf9s43gg.js +0 -1
- package/dist/context/runtime-context-consumer.d.ts +0 -13
- package/dist/context/runtime-context-consumer.js +0 -18
- package/dist/item-loader.d.ts +0 -44
- package/dist/item-loader.js +0 -61
- package/dist/policy/core/engine-context.d.ts +0 -29
- package/dist/policy/core/engine-context.js +0 -27
- package/dist/policy/core/policy-source-tag.d.ts +0 -31
- package/dist/policy/core/policy-source-tag.js +0 -28
- package/dist/policy/internal.d.ts +0 -25
- package/dist/policy/internal.js +0 -25
- package/dist/runtime/adapter/coordinator-bridge.d.ts +0 -92
- package/dist/runtime/adapter/coordinator-bridge.js +0 -126
- package/dist/runtime/adapter/framework-error-bridge.d.ts +0 -36
- package/dist/runtime/adapter/framework-error-bridge.js +0 -46
- package/dist/runtime/adapter/instrumentation-bridge.d.ts +0 -31
- package/dist/runtime/adapter/instrumentation-bridge.js +0 -38
- package/dist/runtime/core/engine-stage-derivation.d.ts +0 -18
- package/dist/runtime/core/engine-stage-derivation.js +0 -29
- package/dist/runtime/engine-context.d.ts +0 -39
- package/dist/runtime/engine-context.js +0 -31
- package/dist/runtime/internal.d.ts +0 -43
- package/dist/runtime/internal.js +0 -45
- package/dist/runtime/section-runtime-engine-host-context.d.ts +0 -74
- package/dist/runtime/section-runtime-engine-host-context.js +0 -57
- package/dist/runtime/stage-emit-gate.d.ts +0 -92
- package/dist/runtime/stage-emit-gate.js +0 -82
- package/dist/services/ContextVariableStore.d.ts +0 -113
- package/dist/services/ContextVariableStore.js +0 -206
- package/dist/services/I18nService.d.ts +0 -47
- package/dist/services/I18nService.js +0 -84
- package/dist/services/ThemeProvider.d.ts +0 -95
- package/dist/services/ThemeProvider.js +0 -334
- package/dist/services/defaultPersonalNeedsProfile.d.ts +0 -21
- package/dist/services/defaultPersonalNeedsProfile.js +0 -26
- package/dist/services/pnp-standard-features.d.ts +0 -238
- package/dist/services/pnp-standard-features.js +0 -338
- package/dist/services/tts-control-events.d.ts +0 -13
- package/dist/services/tts-control-events.js +0 -7
- package/dist/tools/client.d.ts +0 -10
- package/dist/tools/client.js +0 -10
- package/dist/tools/internal.d.ts +0 -44
- package/dist/tools/internal.js +0 -39
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.js +0 -10
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PNP Policy Source
|
|
3
|
-
* (see
|
|
2
|
+
* PNP Policy Source: step 5 of `composeDecision` (see
|
|
4
3
|
* `docs/tools-and-accomodations/architecture.md`).
|
|
5
4
|
*
|
|
6
5
|
* This source applies the PNP/profile precedence rules as a `(candidates, pnpPolicyInputs) →
|
|
@@ -16,12 +15,15 @@ export class PnpPolicySource {
|
|
|
16
15
|
}
|
|
17
16
|
apply(args) {
|
|
18
17
|
const { ctx, result } = this.prepare(args);
|
|
19
|
-
const { pnp, districtPolicy, itemSettings } = ctx;
|
|
18
|
+
const { pnp, districtPolicy, testAdmin, itemSettings } = ctx;
|
|
20
19
|
const allSupports = new Set();
|
|
21
20
|
pnp?.supports?.forEach((s) => allSupports.add(s));
|
|
22
21
|
pnp?.prohibitedSupports?.forEach((s) => allSupports.add(s));
|
|
23
22
|
districtPolicy?.blockedTools?.forEach((s) => allSupports.add(s));
|
|
24
23
|
districtPolicy?.requiredTools?.forEach((s) => allSupports.add(s));
|
|
24
|
+
for (const s of Object.keys(testAdmin?.toolOverrides ?? {})) {
|
|
25
|
+
allSupports.add(s);
|
|
26
|
+
}
|
|
25
27
|
itemSettings?.requiredTools?.forEach((s) => allSupports.add(s));
|
|
26
28
|
itemSettings?.restrictedTools?.forEach((s) => allSupports.add(s));
|
|
27
29
|
for (const supportId of allSupports) {
|
|
@@ -30,20 +32,18 @@ export class PnpPolicySource {
|
|
|
30
32
|
return result;
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
|
-
* Evaluate exactly one PNP support id through the same
|
|
35
|
+
* Evaluate exactly one PNP support id through the same eight-level
|
|
34
36
|
* precedence `apply(...)` uses.
|
|
35
37
|
*
|
|
36
38
|
* This exists for **policy-addressable capabilities that are not toolbar
|
|
37
39
|
* tools** — a signed alternate rendered as its own region, for example.
|
|
38
40
|
* `apply(...)` only evaluates support ids that appear somewhere in the
|
|
39
|
-
* bound policy inputs
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* Evaluating one id in isolation avoids both problems: the returned result
|
|
43
|
-
* carries exactly one decision, and `decisions[0].action` is the verdict.
|
|
41
|
+
* bound policy inputs. Evaluating one id in isolation answers for any
|
|
42
|
+
* feature: the returned result carries exactly one decision, and
|
|
43
|
+
* `decisions[0].action` is the verdict.
|
|
44
44
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* It reuses `resolveSupport(...)` because a second copy of the eight levels
|
|
46
|
+
* would drift.
|
|
47
47
|
*/
|
|
48
48
|
resolveFeature(featureId, args) {
|
|
49
49
|
const { ctx, result } = this.prepare(args);
|
|
@@ -55,16 +55,16 @@ export class PnpPolicySource {
|
|
|
55
55
|
* configuration-source attribution) from the bound policy inputs.
|
|
56
56
|
*/
|
|
57
57
|
prepare(args) {
|
|
58
|
-
const { assessment,
|
|
58
|
+
const { assessment, item } = args;
|
|
59
59
|
const pnp = assessment?.personalNeedsProfile;
|
|
60
60
|
const settings = assessment?.settings;
|
|
61
|
-
const itemSettings =
|
|
61
|
+
const itemSettings = item?.settings;
|
|
62
62
|
const result = {
|
|
63
63
|
blockedToolIds: new Set(),
|
|
64
|
-
|
|
64
|
+
mandates: new Map(),
|
|
65
65
|
perToolFlags: new Map(),
|
|
66
66
|
decisions: [],
|
|
67
|
-
|
|
67
|
+
blockedOverrides: new Map(),
|
|
68
68
|
sources: {},
|
|
69
69
|
};
|
|
70
70
|
if (settings?.districtPolicy || settings?.testAdministration) {
|
|
@@ -81,11 +81,11 @@ export class PnpPolicySource {
|
|
|
81
81
|
config: pnp,
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
if (
|
|
84
|
+
if (item) {
|
|
85
85
|
result.sources.item = {
|
|
86
|
-
id:
|
|
87
|
-
name:
|
|
88
|
-
config:
|
|
86
|
+
id: item.id,
|
|
87
|
+
name: item.id,
|
|
88
|
+
config: item.settings,
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
const ctx = {
|
|
@@ -93,19 +93,17 @@ export class PnpPolicySource {
|
|
|
93
93
|
districtPolicy: settings?.districtPolicy,
|
|
94
94
|
testAdmin: settings?.testAdministration,
|
|
95
95
|
itemSettings,
|
|
96
|
-
toolConfigs: settings?.toolConfigs,
|
|
97
96
|
};
|
|
98
97
|
return { ctx, result };
|
|
99
98
|
}
|
|
100
99
|
resolveSupport(supportId, ctx, out) {
|
|
101
100
|
// 1. District block (absolute veto)
|
|
102
101
|
if (ctx.districtPolicy?.blockedTools?.includes(supportId)) {
|
|
103
|
-
|
|
104
|
-
out.blockedToolIds.add(toolId);
|
|
102
|
+
out.blockedToolIds.add(supportId);
|
|
105
103
|
out.decisions.push({
|
|
106
104
|
precedence: 1,
|
|
107
105
|
rule: "district-block",
|
|
108
|
-
featureId:
|
|
106
|
+
featureId: supportId,
|
|
109
107
|
action: "block",
|
|
110
108
|
sourceType: "assessment",
|
|
111
109
|
reason: `District policy blocks "${supportId}" for all assessments`,
|
|
@@ -113,29 +111,32 @@ export class PnpPolicySource {
|
|
|
113
111
|
});
|
|
114
112
|
return;
|
|
115
113
|
}
|
|
116
|
-
// 2. Test administration override
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
// 2. Test administration override `false`: withdraws the support for the
|
|
115
|
+
// session, outranking every level below.
|
|
116
|
+
const override = ctx.testAdmin?.toolOverrides?.[supportId];
|
|
117
|
+
if (override === false) {
|
|
118
|
+
out.blockedToolIds.add(supportId);
|
|
120
119
|
out.decisions.push({
|
|
121
120
|
precedence: 2,
|
|
122
121
|
rule: "test-admin-override",
|
|
123
|
-
featureId:
|
|
122
|
+
featureId: supportId,
|
|
124
123
|
action: "block",
|
|
125
124
|
sourceType: "assessment",
|
|
126
125
|
reason: `Test administrator disabled "${supportId}" for this session`,
|
|
127
|
-
value: ctx.testAdmin
|
|
126
|
+
value: ctx.testAdmin?.toolOverrides,
|
|
128
127
|
});
|
|
129
128
|
return;
|
|
130
129
|
}
|
|
131
130
|
// 3. Item restriction (per-item block)
|
|
132
131
|
if (ctx.itemSettings?.restrictedTools?.includes(supportId)) {
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
out.blockedToolIds.add(supportId);
|
|
133
|
+
if (override === true) {
|
|
134
|
+
out.blockedOverrides.set(supportId, "item-restriction");
|
|
135
|
+
}
|
|
135
136
|
out.decisions.push({
|
|
136
137
|
precedence: 3,
|
|
137
138
|
rule: "item-restriction",
|
|
138
|
-
featureId:
|
|
139
|
+
featureId: supportId,
|
|
139
140
|
action: "block",
|
|
140
141
|
sourceType: "item",
|
|
141
142
|
reason: `Item restricts "${supportId}" (e.g., mental math question blocks calculator)`,
|
|
@@ -143,78 +144,99 @@ export class PnpPolicySource {
|
|
|
143
144
|
});
|
|
144
145
|
return;
|
|
145
146
|
}
|
|
146
|
-
// 4.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
out.
|
|
150
|
-
|
|
147
|
+
// 4. Profile prohibition: the student's profile withdraws the support,
|
|
148
|
+
// outranking a `true` override and every requirement.
|
|
149
|
+
if (ctx.pnp?.prohibitedSupports?.includes(supportId)) {
|
|
150
|
+
out.blockedToolIds.add(supportId);
|
|
151
|
+
if (override === true) {
|
|
152
|
+
out.blockedOverrides.set(supportId, "pnp-prohibited");
|
|
153
|
+
}
|
|
154
|
+
out.decisions.push({
|
|
155
|
+
precedence: 4,
|
|
156
|
+
rule: "pnp-prohibited",
|
|
157
|
+
featureId: supportId,
|
|
158
|
+
action: "block",
|
|
159
|
+
sourceType: "student",
|
|
160
|
+
reason: `Student PNP profile prohibits "${supportId}"`,
|
|
161
|
+
value: ctx.pnp.prohibitedSupports,
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const mandate = ctx.itemSettings?.requiredTools?.includes(supportId)
|
|
166
|
+
? "item-requirement"
|
|
167
|
+
: ctx.districtPolicy?.requiredTools?.includes(supportId)
|
|
168
|
+
? "district-requirement"
|
|
169
|
+
: undefined;
|
|
170
|
+
// 5. Test administration override `true`: grants the support for the
|
|
171
|
+
// session. A requirement naming it keeps its mandate.
|
|
172
|
+
if (override === true) {
|
|
173
|
+
if (mandate)
|
|
174
|
+
out.mandates.set(supportId, mandate);
|
|
175
|
+
out.perToolFlags.set(supportId, {
|
|
176
|
+
required: mandate !== undefined,
|
|
177
|
+
alwaysAvailable: true,
|
|
178
|
+
rule: "test-admin-override",
|
|
179
|
+
});
|
|
180
|
+
out.decisions.push({
|
|
181
|
+
precedence: 5,
|
|
182
|
+
rule: "test-admin-override",
|
|
183
|
+
featureId: supportId,
|
|
184
|
+
action: "enable",
|
|
185
|
+
sourceType: "assessment",
|
|
186
|
+
reason: `Test administrator enabled "${supportId}" for this session`,
|
|
187
|
+
value: ctx.testAdmin?.toolOverrides,
|
|
188
|
+
});
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// 6. Item requirement (forces enable)
|
|
192
|
+
if (mandate === "item-requirement") {
|
|
193
|
+
out.mandates.set(supportId, mandate);
|
|
194
|
+
out.perToolFlags.set(supportId, {
|
|
151
195
|
required: true,
|
|
152
196
|
alwaysAvailable: false,
|
|
153
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
154
197
|
rule: "item-requirement",
|
|
155
|
-
sourceType: "item",
|
|
156
198
|
});
|
|
157
199
|
out.decisions.push({
|
|
158
|
-
precedence:
|
|
200
|
+
precedence: 6,
|
|
159
201
|
rule: "item-requirement",
|
|
160
|
-
featureId:
|
|
202
|
+
featureId: supportId,
|
|
161
203
|
action: "enable",
|
|
162
204
|
sourceType: "item",
|
|
163
205
|
reason: `Item requires "${supportId}" for this question`,
|
|
164
|
-
value: ctx.itemSettings
|
|
206
|
+
value: ctx.itemSettings?.requiredTools,
|
|
165
207
|
});
|
|
166
208
|
return;
|
|
167
209
|
}
|
|
168
|
-
//
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
out.
|
|
172
|
-
out.perToolFlags.set(toolId, {
|
|
210
|
+
// 7. District requirement
|
|
211
|
+
if (mandate === "district-requirement") {
|
|
212
|
+
out.mandates.set(supportId, mandate);
|
|
213
|
+
out.perToolFlags.set(supportId, {
|
|
173
214
|
required: true,
|
|
174
215
|
alwaysAvailable: false,
|
|
175
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
176
216
|
rule: "district-requirement",
|
|
177
|
-
sourceType: "assessment",
|
|
178
217
|
});
|
|
179
218
|
out.decisions.push({
|
|
180
|
-
precedence:
|
|
219
|
+
precedence: 7,
|
|
181
220
|
rule: "district-requirement",
|
|
182
|
-
featureId:
|
|
221
|
+
featureId: supportId,
|
|
183
222
|
action: "enable",
|
|
184
223
|
sourceType: "assessment",
|
|
185
224
|
reason: `District policy requires "${supportId}" for all assessments`,
|
|
186
|
-
value: ctx.districtPolicy
|
|
187
|
-
});
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
// 6. PNP prohibitions and supports (student needs)
|
|
191
|
-
if (ctx.pnp?.prohibitedSupports?.includes(supportId)) {
|
|
192
|
-
const toolId = this.mapSupportToToolId(supportId, out);
|
|
193
|
-
out.blockedToolIds.add(toolId);
|
|
194
|
-
out.decisions.push({
|
|
195
|
-
precedence: 6,
|
|
196
|
-
rule: "pnp-prohibited",
|
|
197
|
-
featureId: toolId,
|
|
198
|
-
action: "block",
|
|
199
|
-
sourceType: "student",
|
|
200
|
-
reason: `Student PNP profile prohibits "${supportId}"`,
|
|
201
|
-
value: ctx.pnp.prohibitedSupports,
|
|
225
|
+
value: ctx.districtPolicy?.requiredTools,
|
|
202
226
|
});
|
|
203
227
|
return;
|
|
204
228
|
}
|
|
229
|
+
// 8. Profile supports (student needs)
|
|
205
230
|
if (ctx.pnp?.supports?.includes(supportId)) {
|
|
206
|
-
|
|
207
|
-
out.perToolFlags.set(toolId, {
|
|
231
|
+
out.perToolFlags.set(supportId, {
|
|
208
232
|
required: false,
|
|
209
233
|
alwaysAvailable: true,
|
|
210
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
211
234
|
rule: "pnp-support",
|
|
212
|
-
sourceType: "student",
|
|
213
235
|
});
|
|
214
236
|
out.decisions.push({
|
|
215
|
-
precedence:
|
|
237
|
+
precedence: 8,
|
|
216
238
|
rule: "pnp-support",
|
|
217
|
-
featureId:
|
|
239
|
+
featureId: supportId,
|
|
218
240
|
action: "enable",
|
|
219
241
|
sourceType: "student",
|
|
220
242
|
reason: `Student PNP profile requests "${supportId}"`,
|
|
@@ -222,16 +244,12 @@ export class PnpPolicySource {
|
|
|
222
244
|
});
|
|
223
245
|
return;
|
|
224
246
|
}
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
// the same way as every other branch — PR 5's debugger surfaces
|
|
228
|
-
// index provenance trails by tool id and would otherwise show
|
|
229
|
-
// orphaned support-id entries here (M8 PR 1 R3 S1).
|
|
230
|
-
const toolId = this.mapSupportToToolId(supportId, out);
|
|
247
|
+
// 8 (skip): no rule fired. The trail is keyed by tool id, as in every
|
|
248
|
+
// other branch.
|
|
231
249
|
out.decisions.push({
|
|
232
|
-
precedence:
|
|
250
|
+
precedence: 8,
|
|
233
251
|
rule: "pnp-support",
|
|
234
|
-
featureId:
|
|
252
|
+
featureId: supportId,
|
|
235
253
|
action: "skip",
|
|
236
254
|
sourceType: "system",
|
|
237
255
|
reason: `Feature "${supportId}" not configured at any level`,
|
|
@@ -239,59 +257,42 @@ export class PnpPolicySource {
|
|
|
239
257
|
});
|
|
240
258
|
}
|
|
241
259
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* returns a `Set<string>` whose iteration order matches the
|
|
250
|
-
* `register(...)` insertion order, so the result is
|
|
251
|
-
* deterministic across runs but order-sensitive at registration
|
|
252
|
-
* time. This is an unusual configuration — the typical case is
|
|
253
|
-
* one tool per support id — but it is reachable when an
|
|
254
|
-
* integrator overrides a default tool with a replacement that
|
|
255
|
-
* claims the same `pnpSupportIds`. In that case the integrator
|
|
256
|
-
* should `unregister(...)` the default before registering the
|
|
257
|
-
* replacement.
|
|
258
|
-
*
|
|
259
|
-
* 2. **No tool registers the support id:** the support id is
|
|
260
|
-
* returned verbatim as the `featureId` for provenance trails
|
|
261
|
-
* and `ToolPolicyEntry.toolId`. This lets hosts use raw QTI
|
|
262
|
-
* strings for tools the registry does not (yet) carry without
|
|
263
|
-
* losing them in policy evaluation.
|
|
264
|
-
*
|
|
265
|
-
* `tests/policy/PnpPolicySource.test.ts` locks this mapping behavior.
|
|
260
|
+
* Ids the assessment or any of `items` names that no tool is registered
|
|
261
|
+
* under, each with the rules whose lists name it, in precedence order. A
|
|
262
|
+
* support id is the id of the tool it grants, so an id missing from the
|
|
263
|
+
* registry matches nothing placed; the engine turns each into a
|
|
264
|
+
* `tool-policy.unknownSupportId` diagnostic. Empty when the registry is: an
|
|
265
|
+
* empty registry has nothing to check an id against, and
|
|
266
|
+
* `tool-config-validation` already reports it once.
|
|
266
267
|
*/
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
268
|
+
unknownSupportIds(assessment, items) {
|
|
269
|
+
const unmapped = new Map();
|
|
270
|
+
if (this.toolRegistry.getAllTools().length === 0)
|
|
271
|
+
return unmapped;
|
|
272
|
+
const pnp = assessment?.personalNeedsProfile;
|
|
273
|
+
const settings = assessment?.settings;
|
|
274
|
+
const named = [
|
|
275
|
+
["district-block", settings?.districtPolicy?.blockedTools],
|
|
276
|
+
[
|
|
277
|
+
"test-admin-override",
|
|
278
|
+
Object.keys(settings?.testAdministration?.toolOverrides ?? {}),
|
|
279
|
+
],
|
|
280
|
+
["item-restriction", items.flatMap((item) => item.restrictedTools ?? [])],
|
|
281
|
+
["pnp-prohibited", pnp?.prohibitedSupports],
|
|
282
|
+
["item-requirement", items.flatMap((item) => item.requiredTools ?? [])],
|
|
283
|
+
["district-requirement", settings?.districtPolicy?.requiredTools],
|
|
284
|
+
["pnp-support", pnp?.supports],
|
|
285
|
+
];
|
|
286
|
+
for (const [rule, ids] of named) {
|
|
287
|
+
for (const id of ids ?? []) {
|
|
288
|
+
if (this.toolRegistry.has(id))
|
|
289
|
+
continue;
|
|
290
|
+
const rules = unmapped.get(id) ?? [];
|
|
291
|
+
if (!rules.includes(rule))
|
|
292
|
+
rules.push(rule);
|
|
293
|
+
unmapped.set(id, rules);
|
|
276
294
|
}
|
|
277
|
-
return supportId;
|
|
278
295
|
}
|
|
279
|
-
return
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Resolve tool-specific settings, item-level taking precedence over
|
|
283
|
-
* assessment-level.
|
|
284
|
-
*
|
|
285
|
-
* Uses `??` (nullish-coalescing). Tool config values are typed `unknown` and may legitimately
|
|
286
|
-
* be `false` / `0` / `""` (e.g. a tool whose canonical "off" config
|
|
287
|
-
* is the literal `false`). `||` would treat those as missing and
|
|
288
|
-
* silently fall through to the assessment-level config, masking the
|
|
289
|
-
* authored item-level intent. `??` only falls through on
|
|
290
|
-
* `null`/`undefined`, which matches the semantic of "value not
|
|
291
|
-
* provided."
|
|
292
|
-
*/
|
|
293
|
-
resolveToolSettings(supportId, ctx) {
|
|
294
|
-
return (ctx.itemSettings?.toolParameters?.[supportId] ??
|
|
295
|
-
ctx.toolConfigs?.[supportId]);
|
|
296
|
+
return unmapped;
|
|
296
297
|
}
|
|
297
298
|
}
|