@pie-players/pie-assessment-toolkit 0.3.75 → 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 +449 -541
- package/custom-elements.json +1315 -0
- package/dist/attempt/TestSession.d.ts +0 -1
- package/dist/attempt/TestSession.js +10 -5
- package/dist/components/ItemScope.custom-element.js +1 -1
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +8 -8
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/{ItemToolBar-7tt7v2xp.js → ItemToolBar-3zrc4p3d.js} +4 -4
- package/dist/components/chunks/{ItemToolBar-jx38w99s.js → ItemToolBar-66hcwmfw.js} +2 -2
- package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
- package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
- package/dist/components/chunks/{ItemToolBar-97hx60z4.js → ItemToolBar-kkj69ptr.js} +1 -1
- package/dist/components/chunks/sre-engine-bj997w4b.js +1 -0
- package/dist/context/assessment-toolkit-context.d.ts +6 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +4 -10
- package/dist/policy/core/PolicySource.d.ts +1 -1
- package/dist/policy/core/ToolPolicyEngine.d.ts +46 -7
- package/dist/policy/core/ToolPolicyEngine.js +73 -16
- package/dist/policy/core/compose-decision.d.ts +3 -3
- package/dist/policy/core/compose-decision.js +30 -30
- package/dist/policy/core/decision-types.d.ts +44 -32
- package/dist/policy/core/feature-decision.d.ts +17 -15
- package/dist/policy/core/feature-decision.js +11 -13
- package/dist/policy/core/pnp-policy-inputs.d.ts +5 -2
- package/dist/policy/core/pnp-policy-inputs.js +12 -32
- package/dist/policy/core/provenance.d.ts +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 +1 -1
- package/dist/policy/sources/PnpPolicySource.d.ts +14 -22
- package/dist/policy/sources/PnpPolicySource.js +30 -28
- package/dist/runtime/SectionControllerBinding.d.ts +6 -2
- package/dist/runtime/SectionControllerBinding.js +21 -15
- package/dist/runtime/adapter/subscriber-fanout.d.ts +0 -1
- package/dist/runtime/adapter/subscriber-fanout.js +1 -4
- package/dist/runtime/composition-emit-scheduler.d.ts +3 -3
- package/dist/runtime/composition-emit-scheduler.js +1 -1
- package/dist/runtime/content-region.d.ts +0 -4
- package/dist/runtime/content-region.js +2 -2
- package/dist/runtime/core/SectionEngineCore.d.ts +0 -2
- package/dist/runtime/core/SectionEngineCore.js +0 -4
- package/dist/runtime/core/cohort.d.ts +0 -5
- package/dist/runtime/core/cohort.js +0 -9
- package/dist/runtime/core/engine-output.d.ts +3 -2
- package/dist/runtime/core/engine-transition.js +3 -2
- package/dist/runtime/registration-events.d.ts +11 -14
- package/dist/runtime/runtime-id.d.ts +1 -1
- package/dist/runtime/runtime-id.js +1 -1
- package/dist/runtime/shell-scope.d.ts +4 -4
- package/dist/runtime/shell-scope.js +15 -9
- package/dist/runtime/tool-host-contract.d.ts +0 -4
- package/dist/runtime/tool-host-contract.js +1 -1
- package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
- package/dist/services/AccessibilityCatalogResolver.js +29 -42
- package/dist/services/ElementToolStateStore.d.ts +32 -61
- package/dist/services/ElementToolStateStore.js +37 -67
- package/dist/services/HighlightCoordinator.d.ts +9 -21
- package/dist/services/HighlightCoordinator.js +52 -80
- package/dist/services/RangeSerializer.d.ts +4 -35
- package/dist/services/RangeSerializer.js +4 -48
- package/dist/services/SSMLExtractor.d.ts +8 -31
- package/dist/services/SSMLExtractor.js +18 -40
- package/dist/services/TTSService.d.ts +49 -56
- package/dist/services/TTSService.js +308 -283
- package/dist/services/ToolCoordinator.d.ts +6 -49
- package/dist/services/ToolCoordinator.js +25 -61
- package/dist/services/ToolRegistry.d.ts +82 -80
- package/dist/services/ToolRegistry.js +91 -67
- package/dist/services/ToolkitCoordinator.d.ts +83 -81
- package/dist/services/ToolkitCoordinator.js +186 -174
- package/dist/services/framework-error.d.ts +30 -7
- package/dist/services/framework-error.js +10 -13
- package/dist/services/interfaces.d.ts +47 -71
- package/dist/services/section-controller-types.d.ts +7 -7
- package/dist/services/section-session-assignment.js +6 -8
- package/dist/services/spoken-audio-cards.d.ts +2 -4
- package/dist/services/spoken-audio-cards.js +2 -4
- package/dist/services/tool-config-validation.d.ts +5 -7
- package/dist/services/tool-config-validation.js +11 -26
- package/dist/services/tool-context.d.ts +7 -23
- package/dist/services/tool-context.js +99 -53
- package/dist/services/tool-failure.d.ts +30 -0
- package/dist/services/tool-failure.js +11 -0
- package/dist/services/tool-icons.d.ts +1 -2
- package/dist/services/tool-icons.js +2 -2
- package/dist/services/tool-instance-id.d.ts +8 -6
- package/dist/services/tool-instance-id.js +12 -18
- package/dist/services/tool-providers/TTSToolProvider.d.ts +6 -43
- package/dist/services/tool-providers/TTSToolProvider.js +7 -63
- package/dist/services/tool-providers/ToolProviderApi.d.ts +0 -7
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +7 -42
- package/dist/services/tool-providers/ToolProviderRegistry.js +21 -63
- package/dist/services/tool-request.d.ts +4 -0
- package/dist/services/tool-request.js +7 -2
- package/dist/services/toolbar-decided-tools.d.ts +1 -0
- package/dist/services/toolbar-decided-tools.js +1 -0
- package/dist/services/toolbar-items.js +2 -5
- package/dist/services/tools-config-normalizer.d.ts +18 -9
- package/dist/services/tools-config-normalizer.js +25 -19
- package/dist/services/tts/browser-provider.d.ts +2 -5
- package/dist/services/tts/browser-provider.js +4 -20
- package/dist/services/tts/catalog-span-alignment.js +14 -7
- package/dist/services/tts/flat-tree.d.ts +0 -7
- package/dist/services/tts/flat-tree.js +2 -2
- 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/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 +10 -12
- package/dist/services/tts/highlight-target-resolver.d.ts +12 -0
- package/dist/services/tts/math-aware-text-processing.js +10 -29
- package/dist/services/tts/math-speech.d.ts +1 -1
- package/dist/services/tts/math-speech.js +3 -0
- 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 +12 -1
- package/dist/services/tts/ssml/spoken-text.js +1 -1
- package/dist/services/tts/start-failure.d.ts +0 -7
- package/dist/services/tts/start-failure.js +1 -1
- package/dist/services/tts/text-segmentation.d.ts +5 -0
- package/dist/services/tts/text-segmentation.js +13 -10
- package/dist/services/tts-runtime-config.d.ts +32 -12
- package/dist/services/tts-runtime-config.js +14 -20
- package/dist/tools/content-capability-resolution.d.ts +2 -2
- package/dist/tools/registration.d.ts +6 -5
- package/dist/tools/registration.js +10 -9
- package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
- package/dist/tools/registrations/toolbar-registration-helpers.js +6 -0
- package/dist/tools/tool-surface-host.js +1 -8
- package/package.json +8 -6
- package/dist/components/chunks/ItemToolBar-bxwyhr5p.js +0 -2
- package/dist/components/chunks/ItemToolBar-rd2bb4p6.js +0 -40
- package/dist/components/chunks/sre-engine-jd8cc08x.js +0 -1
- package/dist/services/ContextVariableStore.d.ts +0 -113
- package/dist/services/ContextVariableStore.js +0 -206
- package/dist/services/tts-control-events.d.ts +0 -13
- package/dist/services/tts-control-events.js +0 -7
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.js +0 -10
|
@@ -50,8 +50,10 @@ export interface ToolPolicyDecisionRequest {
|
|
|
50
50
|
/**
|
|
51
51
|
* Diagnostic codes the engine may emit alongside a decision.
|
|
52
52
|
* `tool-policy.requiredToolBlocked` fires when a host policy gate
|
|
53
|
-
* (`policy.blocked`,
|
|
54
|
-
* that item or district `requiredTools` mandates.
|
|
53
|
+
* (`policy.blocked`, the allowlist, a provider veto, or placement at no level)
|
|
54
|
+
* removed a tool that item or district `requiredTools` mandates. A tool placed
|
|
55
|
+
* at another level is served there, so its absence from this level's placement
|
|
56
|
+
* is no conflict. `details` is {@link RequiredToolBlockedDetails}.
|
|
55
57
|
*
|
|
56
58
|
* `tool-policy.placementMissing` fires when a custom `PolicySource`
|
|
57
59
|
* references a tool ID that is not present in `tools.placement[level]`
|
|
@@ -62,7 +64,9 @@ export interface ToolPolicyDecisionRequest {
|
|
|
62
64
|
*
|
|
63
65
|
* `tool-policy.unknownSupportId` fires for each id a profile, district
|
|
64
66
|
* policy, test administration or item names that no tool is registered under.
|
|
65
|
-
*
|
|
67
|
+
* It describes the inputs, so the engine reports it on its resolved inputs'
|
|
68
|
+
* `diagnostics` rather than on a decision. `details` is
|
|
69
|
+
* {@link UnknownSupportIdDetails}.
|
|
66
70
|
*
|
|
67
71
|
* `tool-policy.itemSettingNotApplied` fires on a section-, assessment- or
|
|
68
72
|
* passage-level decision for each tool on that toolbar a mounted item's
|
|
@@ -75,9 +79,10 @@ export interface ToolPolicyDecisionRequest {
|
|
|
75
79
|
* `restrictedTools` or the profile's `prohibitedSupports` withdraws instead.
|
|
76
80
|
* `details` is {@link OverrideBlockedDetails}.
|
|
77
81
|
*
|
|
78
|
-
* The toolkit coordinator logs each diagnostic once per code, tool and item
|
|
82
|
+
* The toolkit coordinator logs each diagnostic once per code, tool and item,
|
|
83
|
+
* and hands the same ones to its `onPolicyDiagnostic` listeners.
|
|
79
84
|
*/
|
|
80
|
-
export type ToolPolicyDiagnosticCode =
|
|
85
|
+
export type ToolPolicyDiagnosticCode = keyof ToolPolicyDiagnosticDetails;
|
|
81
86
|
/**
|
|
82
87
|
* Which host gate removed a profile-mandated tool. Surfaced inside
|
|
83
88
|
* `ToolPolicyDiagnostic.details` for `tool-policy.requiredToolBlocked`
|
|
@@ -87,44 +92,38 @@ export type ToolPolicyDiagnosticCode = "tool-policy.requiredToolBlocked" | "tool
|
|
|
87
92
|
* `provenance.features[toolId].allDecisions`.
|
|
88
93
|
*
|
|
89
94
|
* The four values mirror steps 1–4 of `composeDecision`:
|
|
90
|
-
* - `placement-missing` —
|
|
95
|
+
* - `placement-missing` — no level of `tools.placement` lists the tool
|
|
91
96
|
* - `provider-disabled` — `tools.providers[id].enabled === false`
|
|
92
97
|
* - `host-allowlist` — non-empty `tools.policy.allowed` excludes the id
|
|
93
98
|
* - `host-blocked` — `tools.policy.blocked` lists the id
|
|
94
99
|
*/
|
|
95
100
|
export type ToolPolicyHostGate = "placement-missing" | "provider-disabled" | "host-allowlist" | "host-blocked";
|
|
96
|
-
/**
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
* always populate this exact shape today and consumers can safely
|
|
101
|
-
* cast.
|
|
102
|
-
*/
|
|
103
|
-
export interface RequiredToolBlockedDetails extends Record<string, unknown> {
|
|
104
|
-
/** The profile policy rule that mandated the tool (e.g. `district-requirement`). */
|
|
105
|
-
rule: string;
|
|
101
|
+
/** Payload of a `tool-policy.requiredToolBlocked` diagnostic. */
|
|
102
|
+
export interface RequiredToolBlockedDetails {
|
|
103
|
+
/** The requirement that mandates the tool. */
|
|
104
|
+
rule: "item-requirement" | "district-requirement";
|
|
106
105
|
/** Which host gate removed the tool. */
|
|
107
106
|
hostRule: ToolPolicyHostGate;
|
|
108
107
|
/** The host configuration value that triggered the gate (best-effort, may be omitted). */
|
|
109
108
|
hostValue?: unknown;
|
|
110
109
|
}
|
|
111
110
|
/** Payload of a `tool-policy.unknownSupportId` diagnostic. */
|
|
112
|
-
export interface UnknownSupportIdDetails
|
|
111
|
+
export interface UnknownSupportIdDetails {
|
|
113
112
|
/** The rules whose lists name the id, in precedence order. */
|
|
114
113
|
origins: PnpPolicySourceRule[];
|
|
115
114
|
}
|
|
116
115
|
/** Payload of a `tool-policy.placementMissing` diagnostic. */
|
|
117
|
-
export interface PlacementMissingDetails
|
|
116
|
+
export interface PlacementMissingDetails {
|
|
118
117
|
/** The custom `PolicySource` that named the tool. */
|
|
119
118
|
customSourceId: string;
|
|
120
119
|
}
|
|
121
120
|
/** Payload of a `tool-policy.overrideBlocked` diagnostic. */
|
|
122
|
-
export interface OverrideBlockedDetails
|
|
121
|
+
export interface OverrideBlockedDetails {
|
|
123
122
|
/** The rule that withdrew the granted tool. */
|
|
124
123
|
rule: "item-restriction" | "pnp-prohibited";
|
|
125
124
|
}
|
|
126
125
|
/** Payload of a `tool-policy.itemSettingNotApplied` diagnostic. */
|
|
127
|
-
export interface ItemSettingNotAppliedDetails
|
|
126
|
+
export interface ItemSettingNotAppliedDetails {
|
|
128
127
|
/** Canonical id of the item whose setting names the tool. */
|
|
129
128
|
itemId: string;
|
|
130
129
|
/** The item settings that name it. */
|
|
@@ -132,14 +131,28 @@ export interface ItemSettingNotAppliedDetails extends Record<string, unknown> {
|
|
|
132
131
|
/** The level of the toolbar the tool is on. */
|
|
133
132
|
toolbarLevel: ToolLevel;
|
|
134
133
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
/** The payload each diagnostic code carries. */
|
|
135
|
+
export interface ToolPolicyDiagnosticDetails {
|
|
136
|
+
"tool-policy.requiredToolBlocked": RequiredToolBlockedDetails;
|
|
137
|
+
"tool-policy.placementMissing": PlacementMissingDetails;
|
|
138
|
+
"tool-policy.unknownSupportId": UnknownSupportIdDetails;
|
|
139
|
+
"tool-policy.itemSettingNotApplied": ItemSettingNotAppliedDetails;
|
|
140
|
+
"tool-policy.overrideBlocked": OverrideBlockedDetails;
|
|
142
141
|
}
|
|
142
|
+
/** A policy diagnostic, its `details` typed by its `code`. */
|
|
143
|
+
export type ToolPolicyDiagnostic = {
|
|
144
|
+
[C in ToolPolicyDiagnosticCode]: {
|
|
145
|
+
code: C;
|
|
146
|
+
/**
|
|
147
|
+
* The toolbar level decided; absent on a feature decision and on an input
|
|
148
|
+
* diagnostic.
|
|
149
|
+
*/
|
|
150
|
+
level?: ToolPlacementLevel;
|
|
151
|
+
toolId: string;
|
|
152
|
+
message: string;
|
|
153
|
+
details: ToolPolicyDiagnosticDetails[C];
|
|
154
|
+
};
|
|
155
|
+
}[ToolPolicyDiagnosticCode];
|
|
143
156
|
export interface ToolPolicyEntry {
|
|
144
157
|
toolId: string;
|
|
145
158
|
/**
|
|
@@ -158,12 +171,11 @@ export interface ToolPolicyEntry {
|
|
|
158
171
|
*/
|
|
159
172
|
alwaysAvailable: boolean;
|
|
160
173
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* the assessment entity from above the engine.
|
|
174
|
+
* The tool's parameters: the item's `toolParameters` entry on the item's own
|
|
175
|
+
* toolbar, else the assessment's `toolParameters` entry. Set whether or not a
|
|
176
|
+
* grant admitted the tool.
|
|
165
177
|
*/
|
|
166
|
-
|
|
178
|
+
parameters?: Record<string, unknown>;
|
|
167
179
|
}
|
|
168
180
|
export interface ToolPolicyDecision {
|
|
169
181
|
visibleTools: ToolPolicyEntry[];
|
|
@@ -27,10 +27,10 @@ import type { PnpPolicySourceRule, ToolPolicyResolutionDecision, ToolPolicySourc
|
|
|
27
27
|
* A feature verdict comes from one of the eight PNP precedence levels, or from a
|
|
28
28
|
* host gate that never reaches them: `tools.policy.blocked` and a non-empty
|
|
29
29
|
* `tools.policy.allowed` are absolute for the id they name, exactly as they are
|
|
30
|
-
* on the placement-scoped path.
|
|
30
|
+
* on the placement-scoped path. `"none"` is a feature no rule names.
|
|
31
31
|
*/
|
|
32
|
-
export type FeaturePolicyRule = PnpPolicySourceRule | "host-allowlist" | "host-blocked";
|
|
33
|
-
export interface FeaturePolicyDecision {
|
|
32
|
+
export type FeaturePolicyRule = PnpPolicySourceRule | "host-allowlist" | "host-blocked" | "none";
|
|
33
|
+
export interface FeaturePolicyDecision<P = Record<string, unknown>> {
|
|
34
34
|
/** The PNP/AfA support id that was evaluated (e.g. `"signLanguage"`). */
|
|
35
35
|
featureId: string;
|
|
36
36
|
/**
|
|
@@ -42,7 +42,8 @@ export interface FeaturePolicyDecision {
|
|
|
42
42
|
action: ToolPolicyResolutionDecision["action"];
|
|
43
43
|
/** Which precedence rule produced the verdict. */
|
|
44
44
|
rule: FeaturePolicyRule;
|
|
45
|
-
|
|
45
|
+
/** The rule's precedence level; `null` for `rule: "none"`. */
|
|
46
|
+
precedence: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | null;
|
|
46
47
|
sourceType: ToolPolicySourceType;
|
|
47
48
|
/** Human-readable explanation, suitable for a policy debugger. */
|
|
48
49
|
reason: string;
|
|
@@ -66,20 +67,21 @@ export interface FeaturePolicyDecision {
|
|
|
66
67
|
*/
|
|
67
68
|
assessmentBound: boolean;
|
|
68
69
|
/**
|
|
69
|
-
* `true` when
|
|
70
|
-
*
|
|
70
|
+
* `true` when item or district `requiredTools` mandates the feature, including
|
|
71
|
+
* under a `true` test-administration override.
|
|
71
72
|
*/
|
|
72
73
|
required: boolean;
|
|
73
74
|
/**
|
|
74
|
-
*
|
|
75
|
-
* `
|
|
76
|
-
*
|
|
75
|
+
* The feature's parameters: the item's `toolParameters` entry for an item's
|
|
76
|
+
* scope, else the assessment's `toolParameters` entry, keyed by the feature id.
|
|
77
|
+
* Set on a denial too; a host denial leaves it out.
|
|
77
78
|
*/
|
|
78
|
-
parameters?:
|
|
79
|
+
parameters?: P;
|
|
79
80
|
/**
|
|
80
|
-
* Conflicts found while deciding: a `tool-policy.
|
|
81
|
-
*
|
|
82
|
-
*
|
|
81
|
+
* Conflicts found while deciding: a `tool-policy.overrideBlocked` for a
|
|
82
|
+
* granting override the decision withdrew. Empty on a host denial, which
|
|
83
|
+
* consults no policy source. An id no tool is registered under describes the
|
|
84
|
+
* inputs, so it is reported on the engine inputs' `diagnostics`.
|
|
83
85
|
*/
|
|
84
86
|
diagnostics: ToolPolicyDiagnostic[];
|
|
85
87
|
}
|
|
@@ -97,7 +99,7 @@ export interface FeatureDecisionContext {
|
|
|
97
99
|
* blocklist is a verdict whether or not an assessment was bound, and the flag
|
|
98
100
|
* only ever qualifies a *policy* denial.
|
|
99
101
|
*/
|
|
100
|
-
export declare function hostFeatureDenial(featureId: string, rule: "host-allowlist" | "host-blocked", hostValue: readonly string[], context: FeatureDecisionContext): FeaturePolicyDecision
|
|
102
|
+
export declare function hostFeatureDenial(featureId: string, rule: "host-allowlist" | "host-blocked", hostValue: readonly string[], context: FeatureDecisionContext): FeaturePolicyDecision<never>;
|
|
101
103
|
/**
|
|
102
104
|
* Whether a host gate produced the verdict, rather than a policy source.
|
|
103
105
|
*
|
|
@@ -114,4 +116,4 @@ export declare function isHostDeniedFeature(decision: Pick<FeaturePolicyDecision
|
|
|
114
116
|
* exactly one decision and at most one flags entry — no mapped-tool-id
|
|
115
117
|
* bookkeeping is needed to read it back out.
|
|
116
118
|
*/
|
|
117
|
-
export declare function interpretFeatureResult(featureId: string, result: PnpPolicyResult, context: FeatureDecisionContext): FeaturePolicyDecision
|
|
119
|
+
export declare function interpretFeatureResult<P>(featureId: string, result: PnpPolicyResult, context: FeatureDecisionContext, parameters: P | undefined): FeaturePolicyDecision<P>;
|
|
@@ -20,14 +20,12 @@
|
|
|
20
20
|
* "nothing was bound to ask against" are the same verdict for different
|
|
21
21
|
* reasons, and only the second is a defect.
|
|
22
22
|
*/
|
|
23
|
-
import { overrideBlockedDiagnostic
|
|
23
|
+
import { overrideBlockedDiagnostic } from "./compose-decision.js";
|
|
24
24
|
/**
|
|
25
25
|
* Reason text for a denial that had no assessment to decide against.
|
|
26
26
|
*
|
|
27
|
-
* Used in place of
|
|
28
|
-
*
|
|
29
|
-
* stay as the source reported them: nothing fired, so naming a ninth rule
|
|
30
|
-
* would describe a precedence level that does not exist.
|
|
27
|
+
* Used in place of "not configured", which is true but reads as a completed
|
|
28
|
+
* evaluation.
|
|
31
29
|
*/
|
|
32
30
|
const unboundAssessmentReason = (featureId) => `No assessment is bound, so no policy source could grant "${featureId}"`;
|
|
33
31
|
/**
|
|
@@ -73,17 +71,20 @@ export function isHostDeniedFeature(decision) {
|
|
|
73
71
|
* exactly one decision and at most one flags entry — no mapped-tool-id
|
|
74
72
|
* bookkeeping is needed to read it back out.
|
|
75
73
|
*/
|
|
76
|
-
export function interpretFeatureResult(featureId, result, context) {
|
|
74
|
+
export function interpretFeatureResult(featureId, result, context, parameters) {
|
|
77
75
|
const decision = result.decisions[0];
|
|
78
76
|
const flags = Array.from(result.perToolFlags.values())[0];
|
|
79
77
|
const granted = decision?.action === "enable";
|
|
80
78
|
const reason = decision?.reason ?? `Feature "${featureId}" not configured`;
|
|
79
|
+
// The source logs "no rule fired" as a skip at the last level so the trail
|
|
80
|
+
// stays ordered; the verdict names no rule for it.
|
|
81
|
+
const fired = decision !== undefined && decision.action !== "skip";
|
|
81
82
|
return {
|
|
82
83
|
featureId,
|
|
83
84
|
granted,
|
|
84
85
|
action: decision?.action ?? "skip",
|
|
85
|
-
rule: decision
|
|
86
|
-
precedence: decision
|
|
86
|
+
rule: fired ? decision.rule : "none",
|
|
87
|
+
precedence: fired ? decision.precedence : null,
|
|
87
88
|
sourceType: decision?.sourceType ?? "system",
|
|
88
89
|
// Only a denial is re-worded. An unbound host can still be granted the
|
|
89
90
|
// feature — an item's registered settings carrying `requiredTools` mandate
|
|
@@ -93,11 +94,8 @@ export function interpretFeatureResult(featureId, result, context) {
|
|
|
93
94
|
? reason
|
|
94
95
|
: unboundAssessmentReason(featureId),
|
|
95
96
|
required: Boolean(flags?.required),
|
|
96
|
-
parameters
|
|
97
|
+
parameters,
|
|
97
98
|
assessmentBound: context.assessmentBound,
|
|
98
|
-
diagnostics: [
|
|
99
|
-
...Array.from(result.unmappedSupportIds, ([supportId, origins]) => unknownSupportIdDiagnostic(supportId, origins)),
|
|
100
|
-
...Array.from(result.blockedOverrides, ([toolId, rule]) => overrideBlockedDiagnostic(toolId, rule)),
|
|
101
|
-
],
|
|
99
|
+
diagnostics: Array.from(result.blockedOverrides, ([toolId, rule]) => overrideBlockedDiagnostic(toolId, rule)),
|
|
102
100
|
};
|
|
103
101
|
}
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
* - `settings.districtPolicy` (any `blockedTools` or `requiredTools`),
|
|
16
16
|
* - `settings.testAdministration` (any `toolOverrides` entry),
|
|
17
17
|
* - or, for an item-scoped decision, the item's settings carry
|
|
18
|
-
* `requiredTools` / `restrictedTools
|
|
18
|
+
* `requiredTools` / `restrictedTools`.
|
|
19
|
+
*
|
|
20
|
+
* Tool parameters are no policy material: the engine resolves them whatever the
|
|
21
|
+
* enforcement state.
|
|
19
22
|
*
|
|
20
23
|
* Hosts opt out of the auto-on behavior by passing
|
|
21
24
|
* `pnpEnforcement: "off"` explicitly (engine input or
|
|
@@ -32,7 +35,7 @@ import type { AssessmentEntity, ItemSettings } from "@pie-players/pie-players-sh
|
|
|
32
35
|
export declare function assessmentHasPnpPolicyInputs(assessment: AssessmentEntity | null | undefined): boolean;
|
|
33
36
|
/**
|
|
34
37
|
* Return `true` when an item's settings carry item-level profile policy
|
|
35
|
-
* material (`requiredTools
|
|
38
|
+
* material (`requiredTools` or `restrictedTools`).
|
|
36
39
|
*
|
|
37
40
|
* Used in addition to {@link assessmentHasPnpPolicyInputs} for a decision scoped
|
|
38
41
|
* to the item, so an item with profile-relevant settings engages PNP/profile
|
|
@@ -15,12 +15,16 @@
|
|
|
15
15
|
* - `settings.districtPolicy` (any `blockedTools` or `requiredTools`),
|
|
16
16
|
* - `settings.testAdministration` (any `toolOverrides` entry),
|
|
17
17
|
* - or, for an item-scoped decision, the item's settings carry
|
|
18
|
-
* `requiredTools` / `restrictedTools
|
|
18
|
+
* `requiredTools` / `restrictedTools`.
|
|
19
|
+
*
|
|
20
|
+
* Tool parameters are no policy material: the engine resolves them whatever the
|
|
21
|
+
* enforcement state.
|
|
19
22
|
*
|
|
20
23
|
* Hosts opt out of the auto-on behavior by passing
|
|
21
24
|
* `pnpEnforcement: "off"` explicitly (engine input or
|
|
22
25
|
* `ToolkitCoordinator.setPnpEnforcement("off")`).
|
|
23
26
|
*/
|
|
27
|
+
const hasEntries = (value) => Array.isArray(value) && value.length > 0;
|
|
24
28
|
/**
|
|
25
29
|
* Return `true` when the assessment carries any PNP/profile policy
|
|
26
30
|
* material that the engine's `PnpPolicySource` would consume.
|
|
@@ -32,26 +36,15 @@ export function assessmentHasPnpPolicyInputs(assessment) {
|
|
|
32
36
|
if (!assessment)
|
|
33
37
|
return false;
|
|
34
38
|
const pnp = assessment.personalNeedsProfile;
|
|
35
|
-
if (pnp) {
|
|
36
|
-
|
|
37
|
-
return true;
|
|
38
|
-
if (Array.isArray(pnp.prohibitedSupports) &&
|
|
39
|
-
pnp.prohibitedSupports.length > 0) {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
39
|
+
if (pnp && (hasEntries(pnp.supports) || hasEntries(pnp.prohibitedSupports))) {
|
|
40
|
+
return true;
|
|
42
41
|
}
|
|
43
42
|
const settings = assessment.settings;
|
|
44
43
|
if (settings) {
|
|
45
44
|
const district = settings.districtPolicy;
|
|
46
|
-
if (district
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
if (Array.isArray(district.requiredTools) &&
|
|
52
|
-
district.requiredTools.length > 0) {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
45
|
+
if (district &&
|
|
46
|
+
(hasEntries(district.blockedTools) || hasEntries(district.requiredTools))) {
|
|
47
|
+
return true;
|
|
55
48
|
}
|
|
56
49
|
const overrides = settings.testAdministration?.toolOverrides;
|
|
57
50
|
if (overrides &&
|
|
@@ -64,7 +57,7 @@ export function assessmentHasPnpPolicyInputs(assessment) {
|
|
|
64
57
|
}
|
|
65
58
|
/**
|
|
66
59
|
* Return `true` when an item's settings carry item-level profile policy
|
|
67
|
-
* material (`requiredTools
|
|
60
|
+
* material (`requiredTools` or `restrictedTools`).
|
|
68
61
|
*
|
|
69
62
|
* Used in addition to {@link assessmentHasPnpPolicyInputs} for a decision scoped
|
|
70
63
|
* to the item, so an item with profile-relevant settings engages PNP/profile
|
|
@@ -74,20 +67,7 @@ export function assessmentHasPnpPolicyInputs(assessment) {
|
|
|
74
67
|
export function itemSettingsHavePnpPolicyInputs(settings) {
|
|
75
68
|
if (!settings)
|
|
76
69
|
return false;
|
|
77
|
-
|
|
78
|
-
settings.requiredTools.length > 0) {
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
if (Array.isArray(settings.restrictedTools) &&
|
|
82
|
-
settings.restrictedTools.length > 0) {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
if (settings.toolParameters &&
|
|
86
|
-
typeof settings.toolParameters === "object" &&
|
|
87
|
-
Object.keys(settings.toolParameters).length > 0) {
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
return false;
|
|
70
|
+
return hasEntries(settings.requiredTools) || hasEntries(settings.restrictedTools);
|
|
91
71
|
}
|
|
92
72
|
/**
|
|
93
73
|
* Resolve the auto-mode `pnpEnforcement` for one decision.
|
|
@@ -20,7 +20,7 @@ export interface ToolPolicyResolutionDecision {
|
|
|
20
20
|
/** Monotonic step index across the entire decision log. */
|
|
21
21
|
step: number;
|
|
22
22
|
/**
|
|
23
|
-
* Precedence level. PNP/profile rules use `1`–`
|
|
23
|
+
* Precedence level. PNP/profile rules use `1`–`8`; non-profile rules use `0`
|
|
24
24
|
* for host-side gates, and a custom source, which runs after PNP/profile
|
|
25
25
|
* policy, uses its own or `100 + i` for the `i`th registered source.
|
|
26
26
|
*/
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AssessmentEntity, ToolParametersFor } from "@pie-players/pie-players-shared/types";
|
|
2
|
+
import type { PnpPolicyItem } from "../sources/PnpPolicySource.js";
|
|
3
|
+
/**
|
|
4
|
+
* A tool's parameters for one decision: the item's `toolParameters` entry, else
|
|
5
|
+
* the assessment's `toolParameters` entry.
|
|
6
|
+
*
|
|
7
|
+
* Parameters say how a tool behaves wherever policy shows it, so they reach a
|
|
8
|
+
* tool placed without a grant, and PNP enforcement does not gate them. `item` is
|
|
9
|
+
* set only for a decision about the item's own toolbar or content.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveToolParameters<K extends string>(toolId: K, assessment: AssessmentEntity | null | undefined, item: PnpPolicyItem | undefined): ToolParametersFor<K> | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tool's parameters for one decision: the item's `toolParameters` entry, else
|
|
3
|
+
* the assessment's `toolParameters` entry.
|
|
4
|
+
*
|
|
5
|
+
* Parameters say how a tool behaves wherever policy shows it, so they reach a
|
|
6
|
+
* tool placed without a grant, and PNP enforcement does not gate them. `item` is
|
|
7
|
+
* set only for a decision about the item's own toolbar or content.
|
|
8
|
+
*/
|
|
9
|
+
export function resolveToolParameters(toolId, assessment, item) {
|
|
10
|
+
const settings = assessment?.settings;
|
|
11
|
+
const value = item?.settings.toolParameters?.[toolId] ?? settings?.toolParameters?.[toolId];
|
|
12
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
13
|
+
? value
|
|
14
|
+
: undefined;
|
|
15
|
+
}
|
package/dist/policy/engine.d.ts
CHANGED
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export { ToolPolicyEngine, type PnpEnforcementMode, type ResolvedEngineInputs, type ToolPolicyChangeEvent, type ToolPolicyChangeListener, type ToolPolicyEngineArgs, type ToolPolicyEngineInputs, } from "./core/ToolPolicyEngine.js";
|
|
9
9
|
export { isHostDeniedFeature, type FeaturePolicyDecision, type FeaturePolicyRule, } from "./core/feature-decision.js";
|
|
10
|
-
export type { ItemSettingNotAppliedDetails, OverrideBlockedDetails, PlacementMissingDetails, RequiredToolBlockedDetails, ToolPolicyDecision, ToolPolicyDecisionRequest, ToolPolicyDiagnostic, ToolPolicyDiagnosticCode, ToolPolicyEntry, ToolPolicyHostGate, ToolScope, UnknownSupportIdDetails, } from "./core/decision-types.js";
|
|
10
|
+
export type { ItemSettingNotAppliedDetails, OverrideBlockedDetails, PlacementMissingDetails, RequiredToolBlockedDetails, ToolPolicyDecision, ToolPolicyDecisionRequest, ToolPolicyDiagnostic, ToolPolicyDiagnosticCode, ToolPolicyDiagnosticDetails, ToolPolicyEntry, ToolPolicyHostGate, ToolScope, UnknownSupportIdDetails, } from "./core/decision-types.js";
|
|
11
11
|
export type { PolicySource, PolicySourceDecisionContext, PolicySourceProvenanceEntry, PolicySourceResult, } from "./core/PolicySource.js";
|
|
12
12
|
export type { PnpPolicySourceRule, ToolPolicyDecisionRule, ToolPolicyFeatureTrail, ToolPolicyProvenance, ToolPolicyResolutionDecision, ToolPolicySourceType, } from "./core/provenance.js";
|
|
@@ -20,8 +20,6 @@ export interface PnpPolicyToolFlags {
|
|
|
20
20
|
* override grants it (host UI cannot toggle off).
|
|
21
21
|
*/
|
|
22
22
|
alwaysAvailable: boolean;
|
|
23
|
-
/** Tool-specific settings derived from item / assessment settings. */
|
|
24
|
-
settings?: unknown;
|
|
25
23
|
/** Which PNP/profile rule contributed the surviving verdict. */
|
|
26
24
|
rule: PnpPolicySourceRule;
|
|
27
25
|
}
|
|
@@ -60,11 +58,12 @@ export interface PnpPolicyResult {
|
|
|
60
58
|
*/
|
|
61
59
|
blockedToolIds: Set<string>;
|
|
62
60
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
61
|
+
* Tools PNP/profile policy mandates (item or district `requiredTools`), each
|
|
62
|
+
* with the requirement that names it, including a tool a `true` override
|
|
63
|
+
* decides. Used by the engine to detect `tool-policy.requiredToolBlocked`
|
|
65
64
|
* diagnostics for tools removed by host policy.
|
|
66
65
|
*/
|
|
67
|
-
|
|
66
|
+
mandates: Map<string, "item-requirement" | "district-requirement">;
|
|
68
67
|
/**
|
|
69
68
|
* Per-tool flags merged into surviving `ToolPolicyEntry`s.
|
|
70
69
|
*/
|
|
@@ -75,15 +74,6 @@ export interface PnpPolicyResult {
|
|
|
75
74
|
* support id).
|
|
76
75
|
*/
|
|
77
76
|
decisions: PnpPolicyDecisionEvent[];
|
|
78
|
-
/**
|
|
79
|
-
* Ids named by a profile, district policy, test administration or item that
|
|
80
|
-
* no tool is registered under, each with the rules whose lists name it, in
|
|
81
|
-
* precedence order. Nothing resolves them; the engine turns each into a
|
|
82
|
-
* `tool-policy.unknownSupportId` diagnostic. Empty when the registry is: an
|
|
83
|
-
* empty registry has nothing to check an id against, and
|
|
84
|
-
* `tool-config-validation` already reports it once.
|
|
85
|
-
*/
|
|
86
|
-
unmappedSupportIds: Map<string, PnpPolicySourceRule[]>;
|
|
87
77
|
/**
|
|
88
78
|
* Ids a `true` test-administration override names that an item restriction
|
|
89
79
|
* or a PNP prohibition withdrew instead, each with the rule that did. The
|
|
@@ -125,8 +115,8 @@ export declare class PnpPolicySource {
|
|
|
125
115
|
* feature: the returned result carries exactly one decision, and
|
|
126
116
|
* `decisions[0].action` is the verdict.
|
|
127
117
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
118
|
+
* It reuses `resolveSupport(...)` because a second copy of the eight levels
|
|
119
|
+
* would drift.
|
|
130
120
|
*/
|
|
131
121
|
resolveFeature(featureId: string, args: PnpPolicyApplyArgs): PnpPolicyResult;
|
|
132
122
|
/**
|
|
@@ -136,11 +126,13 @@ export declare class PnpPolicySource {
|
|
|
136
126
|
private prepare;
|
|
137
127
|
private resolveSupport;
|
|
138
128
|
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
129
|
+
* Ids the assessment or any of `items` names that no tool is registered
|
|
130
|
+
* under, each with the rules whose lists name it, in precedence order. A
|
|
131
|
+
* support id is the id of the tool it grants, so an id missing from the
|
|
132
|
+
* registry matches nothing placed; the engine turns each into a
|
|
133
|
+
* `tool-policy.unknownSupportId` diagnostic. Empty when the registry is: an
|
|
134
|
+
* empty registry has nothing to check an id against, and
|
|
135
|
+
* `tool-config-validation` already reports it once.
|
|
142
136
|
*/
|
|
143
|
-
|
|
144
|
-
/** Tool parameters: the item's entry, else the assessment's. */
|
|
145
|
-
private resolveToolSettings;
|
|
137
|
+
unknownSupportIds(assessment: AssessmentEntity | null | undefined, items: readonly ItemSettings[]): Map<string, PnpPolicySourceRule[]>;
|
|
146
138
|
}
|
|
@@ -42,8 +42,8 @@ export class PnpPolicySource {
|
|
|
42
42
|
* feature: the returned result carries exactly one decision, and
|
|
43
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);
|
|
@@ -61,10 +61,9 @@ export class PnpPolicySource {
|
|
|
61
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
|
-
unmappedSupportIds: this.unmappedIds(pnp, settings, itemSettings),
|
|
68
67
|
blockedOverrides: new Map(),
|
|
69
68
|
sources: {},
|
|
70
69
|
};
|
|
@@ -94,7 +93,6 @@ export class PnpPolicySource {
|
|
|
94
93
|
districtPolicy: settings?.districtPolicy,
|
|
95
94
|
testAdmin: settings?.testAdministration,
|
|
96
95
|
itemSettings,
|
|
97
|
-
toolConfigs: settings?.toolConfigs,
|
|
98
96
|
};
|
|
99
97
|
return { ctx, result };
|
|
100
98
|
}
|
|
@@ -164,13 +162,19 @@ export class PnpPolicySource {
|
|
|
164
162
|
});
|
|
165
163
|
return;
|
|
166
164
|
}
|
|
165
|
+
const mandate = ctx.itemSettings?.requiredTools?.includes(supportId)
|
|
166
|
+
? "item-requirement"
|
|
167
|
+
: ctx.districtPolicy?.requiredTools?.includes(supportId)
|
|
168
|
+
? "district-requirement"
|
|
169
|
+
: undefined;
|
|
167
170
|
// 5. Test administration override `true`: grants the support for the
|
|
168
|
-
// session.
|
|
171
|
+
// session. A requirement naming it keeps its mandate.
|
|
169
172
|
if (override === true) {
|
|
173
|
+
if (mandate)
|
|
174
|
+
out.mandates.set(supportId, mandate);
|
|
170
175
|
out.perToolFlags.set(supportId, {
|
|
171
|
-
required:
|
|
176
|
+
required: mandate !== undefined,
|
|
172
177
|
alwaysAvailable: true,
|
|
173
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
174
178
|
rule: "test-admin-override",
|
|
175
179
|
});
|
|
176
180
|
out.decisions.push({
|
|
@@ -185,12 +189,11 @@ export class PnpPolicySource {
|
|
|
185
189
|
return;
|
|
186
190
|
}
|
|
187
191
|
// 6. Item requirement (forces enable)
|
|
188
|
-
if (
|
|
189
|
-
out.
|
|
192
|
+
if (mandate === "item-requirement") {
|
|
193
|
+
out.mandates.set(supportId, mandate);
|
|
190
194
|
out.perToolFlags.set(supportId, {
|
|
191
195
|
required: true,
|
|
192
196
|
alwaysAvailable: false,
|
|
193
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
194
197
|
rule: "item-requirement",
|
|
195
198
|
});
|
|
196
199
|
out.decisions.push({
|
|
@@ -200,17 +203,16 @@ export class PnpPolicySource {
|
|
|
200
203
|
action: "enable",
|
|
201
204
|
sourceType: "item",
|
|
202
205
|
reason: `Item requires "${supportId}" for this question`,
|
|
203
|
-
value: ctx.itemSettings
|
|
206
|
+
value: ctx.itemSettings?.requiredTools,
|
|
204
207
|
});
|
|
205
208
|
return;
|
|
206
209
|
}
|
|
207
210
|
// 7. District requirement
|
|
208
|
-
if (
|
|
209
|
-
out.
|
|
211
|
+
if (mandate === "district-requirement") {
|
|
212
|
+
out.mandates.set(supportId, mandate);
|
|
210
213
|
out.perToolFlags.set(supportId, {
|
|
211
214
|
required: true,
|
|
212
215
|
alwaysAvailable: false,
|
|
213
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
214
216
|
rule: "district-requirement",
|
|
215
217
|
});
|
|
216
218
|
out.decisions.push({
|
|
@@ -220,7 +222,7 @@ export class PnpPolicySource {
|
|
|
220
222
|
action: "enable",
|
|
221
223
|
sourceType: "assessment",
|
|
222
224
|
reason: `District policy requires "${supportId}" for all assessments`,
|
|
223
|
-
value: ctx.districtPolicy
|
|
225
|
+
value: ctx.districtPolicy?.requiredTools,
|
|
224
226
|
});
|
|
225
227
|
return;
|
|
226
228
|
}
|
|
@@ -229,7 +231,6 @@ export class PnpPolicySource {
|
|
|
229
231
|
out.perToolFlags.set(supportId, {
|
|
230
232
|
required: false,
|
|
231
233
|
alwaysAvailable: true,
|
|
232
|
-
settings: this.resolveToolSettings(supportId, ctx),
|
|
233
234
|
rule: "pnp-support",
|
|
234
235
|
});
|
|
235
236
|
out.decisions.push({
|
|
@@ -256,23 +257,29 @@ export class PnpPolicySource {
|
|
|
256
257
|
});
|
|
257
258
|
}
|
|
258
259
|
/**
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
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.
|
|
262
267
|
*/
|
|
263
|
-
|
|
268
|
+
unknownSupportIds(assessment, items) {
|
|
264
269
|
const unmapped = new Map();
|
|
265
270
|
if (this.toolRegistry.getAllTools().length === 0)
|
|
266
271
|
return unmapped;
|
|
272
|
+
const pnp = assessment?.personalNeedsProfile;
|
|
273
|
+
const settings = assessment?.settings;
|
|
267
274
|
const named = [
|
|
268
275
|
["district-block", settings?.districtPolicy?.blockedTools],
|
|
269
276
|
[
|
|
270
277
|
"test-admin-override",
|
|
271
278
|
Object.keys(settings?.testAdministration?.toolOverrides ?? {}),
|
|
272
279
|
],
|
|
273
|
-
["item-restriction",
|
|
280
|
+
["item-restriction", items.flatMap((item) => item.restrictedTools ?? [])],
|
|
274
281
|
["pnp-prohibited", pnp?.prohibitedSupports],
|
|
275
|
-
["item-requirement",
|
|
282
|
+
["item-requirement", items.flatMap((item) => item.requiredTools ?? [])],
|
|
276
283
|
["district-requirement", settings?.districtPolicy?.requiredTools],
|
|
277
284
|
["pnp-support", pnp?.supports],
|
|
278
285
|
];
|
|
@@ -288,9 +295,4 @@ export class PnpPolicySource {
|
|
|
288
295
|
}
|
|
289
296
|
return unmapped;
|
|
290
297
|
}
|
|
291
|
-
/** Tool parameters: the item's entry, else the assessment's. */
|
|
292
|
-
resolveToolSettings(supportId, ctx) {
|
|
293
|
-
return (ctx.itemSettings?.toolParameters?.[supportId] ??
|
|
294
|
-
ctx.toolConfigs?.[supportId]);
|
|
295
|
-
}
|
|
296
298
|
}
|