@pie-players/pie-players-shared 1.0.0-beta.7 → 1.0.0-beta.9

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 (44) hide show
  1. package/README.md +16 -14
  2. package/dist/i18n/catalogs.d.ts +20 -13
  3. package/dist/i18n/catalogs.js +22 -23
  4. package/dist/i18n/language-tags.d.ts +23 -6
  5. package/dist/i18n/language-tags.js +74 -9
  6. package/dist/i18n/messages/en-US.d.ts +21 -4
  7. package/dist/i18n/messages/en-US.js +23 -4
  8. package/dist/i18n/types.d.ts +7 -2
  9. package/dist/index.d.ts +1 -1
  10. package/dist/item-session-control/index.d.ts +16 -0
  11. package/dist/item-session-control/index.js +5 -0
  12. package/dist/{formative → item-session-control}/mastery.d.ts +5 -5
  13. package/dist/{formative → item-session-control}/mastery.js +3 -3
  14. package/dist/{formative → item-session-control}/outcome.d.ts +3 -3
  15. package/dist/{formative → item-session-control}/outcome.js +2 -2
  16. package/dist/{formative → item-session-control}/policy.d.ts +11 -11
  17. package/dist/{formative → item-session-control}/policy.js +12 -12
  18. package/dist/item-session-control/session.d.ts +19 -0
  19. package/dist/{formative → item-session-control}/session.js +12 -12
  20. package/dist/{formative → item-session-control}/state.d.ts +26 -26
  21. package/dist/{formative → item-session-control}/state.js +13 -13
  22. package/dist/{formative → item-session-control}/types.d.ts +38 -40
  23. package/dist/{formative → item-session-control}/types.js +2 -2
  24. package/dist/security/private-hosts.d.ts +27 -0
  25. package/dist/security/private-hosts.js +85 -0
  26. package/dist/timed-media/index.d.ts +1 -1
  27. package/dist/timed-media/index.js +1 -1
  28. package/dist/timed-media/policy.d.ts +2 -2
  29. package/dist/timed-media/policy.js +2 -2
  30. package/dist/timed-media/session.d.ts +1 -1
  31. package/dist/timed-media/session.js +1 -1
  32. package/dist/timed-media/types.d.ts +11 -11
  33. package/dist/tools/term-lookup.d.ts +15 -0
  34. package/dist/tools/term-lookup.js +16 -0
  35. package/dist/types/index.d.ts +32 -18
  36. package/dist/types/interchange.d.ts +66 -4
  37. package/dist/ui/fontawesome.d.ts +51 -0
  38. package/dist/ui/fontawesome.js +122 -0
  39. package/package.json +15 -6
  40. package/dist/formative/index.d.ts +0 -16
  41. package/dist/formative/index.js +0 -5
  42. package/dist/formative/session.d.ts +0 -19
  43. package/dist/i18n/messages/nl-NL.d.ts +0 -639
  44. package/dist/i18n/messages/nl-NL.js +0 -639
@@ -1,13 +1,13 @@
1
- import type { FormativeDeliveryPolicy, FormativeItemPolicy, ResolvedFormativePolicy } from "./types.js";
1
+ import type { ItemSessionControlPolicy, ResolvedItemSessionControlPolicy } from "./types.js";
2
2
  /**
3
3
  * Built-in defaults. `enabled: false` is what makes this contract invisible to
4
- * every section authored before it: an absent `formative` field resolves to a
4
+ * every section authored before it: an absent `itemSessionControl` field resolves to a
5
5
  * disabled policy, and a disabled policy produces no state, no projection and
6
6
  * no control.
7
7
  *
8
8
  * `maxTries: 1` matches QTI 3's `qti-item-session-control@max-attempts` default.
9
9
  */
10
- export declare const FORMATIVE_POLICY_DEFAULTS: ResolvedFormativePolicy;
10
+ export declare const ITEM_SESSION_CONTROL_DEFAULTS: ResolvedItemSessionControlPolicy;
11
11
  /**
12
12
  * Merge built-in defaults, the section policy, and one item ref's override, in
13
13
  * that order. Each field overrides independently, which is the order QTI 3 uses
@@ -17,21 +17,21 @@ export declare const FORMATIVE_POLICY_DEFAULTS: ResolvedFormativePolicy;
17
17
  * section: authored policy is host-supplied data, and a typo in one field should
18
18
  * not cost the learner the whole item.
19
19
  */
20
- export declare function resolveFormativePolicy(sectionPolicy?: FormativeDeliveryPolicy | null, itemPolicy?: FormativeItemPolicy | null): ResolvedFormativePolicy;
20
+ export declare function resolveItemSessionControl(sectionPolicy?: ItemSessionControlPolicy | null, itemPolicy?: ItemSessionControlPolicy | null): ResolvedItemSessionControlPolicy;
21
21
  /**
22
22
  * Resolve one policy per item in section order.
23
23
  *
24
24
  * Keyed by the identifier the caller supplies, which in the section runtime is
25
25
  * the canonical item id — the same key `itemSessions` and the completion map
26
- * use, so a formative state and an item session are always addressable by one
26
+ * use, so Try state and an item session are always addressable by one
27
27
  * id.
28
28
  */
29
- export declare function resolveFormativePolicies(args: {
30
- sectionPolicy?: FormativeDeliveryPolicy | null;
29
+ export declare function resolveItemSessionControls(args: {
30
+ sectionPolicy?: ItemSessionControlPolicy | null;
31
31
  items: ReadonlyArray<{
32
32
  identifier: string;
33
- policy?: FormativeItemPolicy | null;
33
+ policy?: ItemSessionControlPolicy | null;
34
34
  }>;
35
- }): Record<string, ResolvedFormativePolicy>;
36
- /** True when at least one item in the section delivers formatively. */
37
- export declare function isFormativeSectionEnabled(policies: Record<string, ResolvedFormativePolicy>): boolean;
35
+ }): Record<string, ResolvedItemSessionControlPolicy>;
36
+ /** True when at least one item in the section enables item session control. */
37
+ export declare function isItemSessionControlEnabledInSection(policies: Record<string, ResolvedItemSessionControlPolicy>): boolean;
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * Built-in defaults. `enabled: false` is what makes this contract invisible to
3
- * every section authored before it: an absent `formative` field resolves to a
3
+ * every section authored before it: an absent `itemSessionControl` field resolves to a
4
4
  * disabled policy, and a disabled policy produces no state, no projection and
5
5
  * no control.
6
6
  *
7
7
  * `maxTries: 1` matches QTI 3's `qti-item-session-control@max-attempts` default.
8
8
  */
9
- export const FORMATIVE_POLICY_DEFAULTS = {
9
+ export const ITEM_SESSION_CONTROL_DEFAULTS = {
10
10
  enabled: false,
11
11
  maxTries: 1,
12
12
  feedback: "correctness",
@@ -40,21 +40,21 @@ function normalizeRevealTiming(value) {
40
40
  * section: authored policy is host-supplied data, and a typo in one field should
41
41
  * not cost the learner the whole item.
42
42
  */
43
- export function resolveFormativePolicy(sectionPolicy, itemPolicy) {
43
+ export function resolveItemSessionControl(sectionPolicy, itemPolicy) {
44
44
  const enabled = typeof itemPolicy?.enabled === "boolean"
45
45
  ? itemPolicy.enabled
46
46
  : typeof sectionPolicy?.enabled === "boolean"
47
47
  ? sectionPolicy.enabled
48
- : FORMATIVE_POLICY_DEFAULTS.enabled;
48
+ : ITEM_SESSION_CONTROL_DEFAULTS.enabled;
49
49
  const maxTries = normalizeTryLimit(itemPolicy?.maxTries) ??
50
50
  normalizeTryLimit(sectionPolicy?.maxTries) ??
51
- FORMATIVE_POLICY_DEFAULTS.maxTries;
51
+ ITEM_SESSION_CONTROL_DEFAULTS.maxTries;
52
52
  const feedback = normalizeFeedback(itemPolicy?.feedback) ??
53
53
  normalizeFeedback(sectionPolicy?.feedback) ??
54
- FORMATIVE_POLICY_DEFAULTS.feedback;
54
+ ITEM_SESSION_CONTROL_DEFAULTS.feedback;
55
55
  const requestedRevealOn = normalizeRevealTiming(itemPolicy?.revealOn) ??
56
56
  normalizeRevealTiming(sectionPolicy?.revealOn) ??
57
- FORMATIVE_POLICY_DEFAULTS.revealOn;
57
+ ITEM_SESSION_CONTROL_DEFAULTS.revealOn;
58
58
  // `"on-final-try"` has no referent under unlimited Tries — there is no final
59
59
  // Try to reveal on — so it resolves to the only reading that keeps feedback
60
60
  // reachable.
@@ -68,19 +68,19 @@ export function resolveFormativePolicy(sectionPolicy, itemPolicy) {
68
68
  *
69
69
  * Keyed by the identifier the caller supplies, which in the section runtime is
70
70
  * the canonical item id — the same key `itemSessions` and the completion map
71
- * use, so a formative state and an item session are always addressable by one
71
+ * use, so Try state and an item session are always addressable by one
72
72
  * id.
73
73
  */
74
- export function resolveFormativePolicies(args) {
74
+ export function resolveItemSessionControls(args) {
75
75
  const resolved = {};
76
76
  for (const item of args.items) {
77
77
  if (!item?.identifier)
78
78
  continue;
79
- resolved[item.identifier] = resolveFormativePolicy(args.sectionPolicy, item.policy);
79
+ resolved[item.identifier] = resolveItemSessionControl(args.sectionPolicy, item.policy);
80
80
  }
81
81
  return resolved;
82
82
  }
83
- /** True when at least one item in the section delivers formatively. */
84
- export function isFormativeSectionEnabled(policies) {
83
+ /** True when at least one item in the section enables item session control. */
84
+ export function isItemSessionControlEnabledInSection(policies) {
85
85
  return Object.values(policies).some((policy) => policy.enabled);
86
86
  }
@@ -0,0 +1,19 @@
1
+ import type { ItemTryState, TrySectionSlice } from "./types.js";
2
+ export declare const TRY_SLICE_VERSION: 1;
3
+ export declare function toTrySectionSlice(states: Record<string, ItemTryState>): TrySectionSlice;
4
+ /**
5
+ * Validate a persisted slice against the section it is being restored into.
6
+ *
7
+ * Returns `null` for a slice this build cannot read, which the caller treats as
8
+ * "start Try state clean". Rejection is deliberately narrow: it discards
9
+ * Try progress and nothing else, so a version bump here never costs a
10
+ * learner their responses — item sessions travel in the same snapshot and are
11
+ * normalized separately.
12
+ *
13
+ * An absent slice is `null` too, and indistinguishable from a save made
14
+ * without Try state, which is what keeps existing snapshots valid.
15
+ */
16
+ export declare function normalizeTrySectionSlice(args: {
17
+ slice: unknown;
18
+ allowedItemIdentifiers: readonly string[];
19
+ }): Record<string, ItemTryState> | null;
@@ -1,5 +1,5 @@
1
- import { FORMATIVE_ITEM_STATE_VERSION } from "./state.js";
2
- export const FORMATIVE_SLICE_VERSION = 1;
1
+ import { ITEM_TRY_STATE_VERSION } from "./state.js";
2
+ export const TRY_SLICE_VERSION = 1;
3
3
  const CORRECTNESS_VALUES = [
4
4
  "correct",
5
5
  "partial",
@@ -54,14 +54,14 @@ function normalizeItemState(itemIdentifier, value) {
54
54
  if (!value || typeof value !== "object")
55
55
  return null;
56
56
  const raw = value;
57
- if (raw.version !== FORMATIVE_ITEM_STATE_VERSION)
57
+ if (raw.version !== ITEM_TRY_STATE_VERSION)
58
58
  return null;
59
59
  const tryCount = readNonNegativeInteger(raw.tryCount);
60
60
  if (tryCount === undefined)
61
61
  return null;
62
62
  const firstCorrectTry = readNonNegativeInteger(raw.firstCorrectTry);
63
63
  return {
64
- version: FORMATIVE_ITEM_STATE_VERSION,
64
+ version: ITEM_TRY_STATE_VERSION,
65
65
  itemIdentifier,
66
66
  tryCount,
67
67
  revealed: raw.revealed === true,
@@ -72,9 +72,9 @@ function normalizeItemState(itemIdentifier, value) {
72
72
  revealOverride: normalizeRevealOverride(raw.revealOverride),
73
73
  };
74
74
  }
75
- export function toFormativeSectionSlice(states) {
75
+ export function toTrySectionSlice(states) {
76
76
  return {
77
- version: FORMATIVE_SLICE_VERSION,
77
+ version: TRY_SLICE_VERSION,
78
78
  items: { ...states },
79
79
  };
80
80
  }
@@ -82,20 +82,20 @@ export function toFormativeSectionSlice(states) {
82
82
  * Validate a persisted slice against the section it is being restored into.
83
83
  *
84
84
  * Returns `null` for a slice this build cannot read, which the caller treats as
85
- * "start formative state clean". Rejection is deliberately narrow: it discards
86
- * formative progress and nothing else, so a version bump here never costs a
85
+ * "start Try state clean". Rejection is deliberately narrow: it discards
86
+ * Try progress and nothing else, so a version bump here never costs a
87
87
  * learner their responses — item sessions travel in the same snapshot and are
88
88
  * normalized separately.
89
89
  *
90
- * An absent slice is `null` too, and indistinguishable from a pre-formative
91
- * save, which is what keeps existing snapshots valid.
90
+ * An absent slice is `null` too, and indistinguishable from a save made
91
+ * without Try state, which is what keeps existing snapshots valid.
92
92
  */
93
- export function normalizeFormativeSectionSlice(args) {
93
+ export function normalizeTrySectionSlice(args) {
94
94
  const { slice } = args;
95
95
  if (!slice || typeof slice !== "object")
96
96
  return null;
97
97
  const raw = slice;
98
- if (raw.version !== FORMATIVE_SLICE_VERSION)
98
+ if (raw.version !== TRY_SLICE_VERSION)
99
99
  return null;
100
100
  if (!raw.items || typeof raw.items !== "object")
101
101
  return null;
@@ -1,6 +1,6 @@
1
- import type { FormativeFeedbackReveal, FormativeItemState, FormativeItemView, FormativeTryOutcome, ResolvedFormativePolicy } from "./types.js";
2
- export declare const FORMATIVE_ITEM_STATE_VERSION: 1;
3
- export declare function createFormativeItemState(itemIdentifier: string): FormativeItemState;
1
+ import type { FeedbackReveal, ItemTryState, ItemTryView, TryOutcome, ResolvedItemSessionControlPolicy } from "./types.js";
2
+ export declare const ITEM_TRY_STATE_VERSION: 1;
3
+ export declare function createItemTryState(itemIdentifier: string): ItemTryState;
4
4
  /**
5
5
  * Record one Try.
6
6
  *
@@ -8,24 +8,24 @@ export declare function createFormativeItemState(itemIdentifier: string): Format
8
8
  * state can be checked, so a second click landing before the projection
9
9
  * round-trips is dropped rather than spending a Try.
10
10
  */
11
- export declare function recordFormativeTry(args: {
12
- state?: FormativeItemState;
11
+ export declare function recordTry(args: {
12
+ state?: ItemTryState;
13
13
  itemIdentifier: string;
14
- policy: ResolvedFormativePolicy;
15
- outcome: FormativeTryOutcome;
16
- }): FormativeItemState;
14
+ policy: ResolvedItemSessionControlPolicy;
15
+ outcome: TryOutcome;
16
+ }): ItemTryState;
17
17
  /**
18
18
  * Dismiss a reveal and reopen the item for editing. Withdrawing `revealed` is
19
19
  * what withdraws the env override, so the item returns to the section's own
20
20
  * mode.
21
21
  *
22
22
  * A learner action, so it respects the Try budget: an item with none left keeps
23
- * its feedback on screen. `hideFormativeItem` is the host-authority version.
23
+ * its feedback on screen. `hideItemFeedback` is the host-authority version.
24
24
  */
25
- export declare function retryFormativeItem(args: {
26
- state?: FormativeItemState;
27
- policy: ResolvedFormativePolicy;
28
- }): FormativeItemState | undefined;
25
+ export declare function retryItem(args: {
26
+ state?: ItemTryState;
27
+ policy: ResolvedItemSessionControlPolicy;
28
+ }): ItemTryState | undefined;
29
29
  /**
30
30
  * Reveal on host authority — a teacher-driven "show the answer".
31
31
  *
@@ -38,23 +38,23 @@ export declare function retryFormativeItem(args: {
38
38
  * whatever response is there, including none, which is what "show the answer"
39
39
  * means before the learner has answered.
40
40
  */
41
- export declare function revealFormativeItem(args: {
42
- state?: FormativeItemState;
41
+ export declare function revealItemFeedback(args: {
42
+ state?: ItemTryState;
43
43
  itemIdentifier: string;
44
- policy: ResolvedFormativePolicy;
45
- feedback: Exclude<FormativeFeedbackReveal, "none">;
46
- }): FormativeItemState;
44
+ policy: ResolvedItemSessionControlPolicy;
45
+ feedback: Exclude<FeedbackReveal, "none">;
46
+ }): ItemTryState;
47
47
  /**
48
48
  * Withdraw a reveal on host authority. Unlike a learner retry this ignores the
49
49
  * Try budget: a host that revealed an item with no Tries left must be able to
50
50
  * put it back.
51
51
  */
52
- export declare function hideFormativeItem(args: {
53
- state?: FormativeItemState;
54
- policy: ResolvedFormativePolicy;
55
- }): FormativeItemState | undefined;
52
+ export declare function hideItemFeedback(args: {
53
+ state?: ItemTryState;
54
+ policy: ResolvedItemSessionControlPolicy;
55
+ }): ItemTryState | undefined;
56
56
  /** Derive everything a rendering component needs from policy plus state. */
57
- export declare function resolveFormativeItemView(args: {
58
- policy: ResolvedFormativePolicy;
59
- state?: FormativeItemState;
60
- }): FormativeItemView;
57
+ export declare function resolveItemTryView(args: {
58
+ policy: ResolvedItemSessionControlPolicy;
59
+ state?: ItemTryState;
60
+ }): ItemTryView;
@@ -1,7 +1,7 @@
1
- export const FORMATIVE_ITEM_STATE_VERSION = 1;
2
- export function createFormativeItemState(itemIdentifier) {
1
+ export const ITEM_TRY_STATE_VERSION = 1;
2
+ export function createItemTryState(itemIdentifier) {
3
3
  return {
4
- version: FORMATIVE_ITEM_STATE_VERSION,
4
+ version: ITEM_TRY_STATE_VERSION,
5
5
  itemIdentifier,
6
6
  tryCount: 0,
7
7
  revealed: false,
@@ -20,7 +20,7 @@ function shouldReveal(policy, tryCount) {
20
20
  return false;
21
21
  if (policy.revealOn === "on-try")
22
22
  return true;
23
- // Defensive: `resolveFormativePolicy` already coerces `"on-final-try"` to
23
+ // Defensive: `resolveItemSessionControl` already coerces `"on-final-try"` to
24
24
  // `"on-try"` under unlimited Tries, so this branch only guards a
25
25
  // hand-constructed policy.
26
26
  if (policy.maxTries === "unlimited")
@@ -34,8 +34,8 @@ function shouldReveal(policy, tryCount) {
34
34
  * state can be checked, so a second click landing before the projection
35
35
  * round-trips is dropped rather than spending a Try.
36
36
  */
37
- export function recordFormativeTry(args) {
38
- const current = args.state ?? createFormativeItemState(args.itemIdentifier);
37
+ export function recordTry(args) {
38
+ const current = args.state ?? createItemTryState(args.itemIdentifier);
39
39
  if (!args.policy.enabled)
40
40
  return current;
41
41
  const remaining = triesRemaining(args.policy, current.tryCount);
@@ -44,7 +44,7 @@ export function recordFormativeTry(args) {
44
44
  const tryCount = current.tryCount + 1;
45
45
  return {
46
46
  ...current,
47
- version: FORMATIVE_ITEM_STATE_VERSION,
47
+ version: ITEM_TRY_STATE_VERSION,
48
48
  itemIdentifier: args.itemIdentifier,
49
49
  tryCount,
50
50
  revealed: shouldReveal(args.policy, tryCount),
@@ -62,9 +62,9 @@ export function recordFormativeTry(args) {
62
62
  * mode.
63
63
  *
64
64
  * A learner action, so it respects the Try budget: an item with none left keeps
65
- * its feedback on screen. `hideFormativeItem` is the host-authority version.
65
+ * its feedback on screen. `hideItemFeedback` is the host-authority version.
66
66
  */
67
- export function retryFormativeItem(args) {
67
+ export function retryItem(args) {
68
68
  const current = args.state;
69
69
  if (!current || !args.policy.enabled)
70
70
  return current;
@@ -87,8 +87,8 @@ export function retryFormativeItem(args) {
87
87
  * whatever response is there, including none, which is what "show the answer"
88
88
  * means before the learner has answered.
89
89
  */
90
- export function revealFormativeItem(args) {
91
- const current = args.state ?? createFormativeItemState(args.itemIdentifier);
90
+ export function revealItemFeedback(args) {
91
+ const current = args.state ?? createItemTryState(args.itemIdentifier);
92
92
  if (!args.policy.enabled)
93
93
  return current;
94
94
  if (current.revealed && current.revealOverride === args.feedback) {
@@ -101,7 +101,7 @@ export function revealFormativeItem(args) {
101
101
  * Try budget: a host that revealed an item with no Tries left must be able to
102
102
  * put it back.
103
103
  */
104
- export function hideFormativeItem(args) {
104
+ export function hideItemFeedback(args) {
105
105
  const current = args.state;
106
106
  if (!current || !args.policy.enabled)
107
107
  return current;
@@ -119,7 +119,7 @@ function envOverrideFor(policy, revealed, revealOverride) {
119
119
  };
120
120
  }
121
121
  /** Derive everything a rendering component needs from policy plus state. */
122
- export function resolveFormativeItemView(args) {
122
+ export function resolveItemTryView(args) {
123
123
  const { policy } = args;
124
124
  const tryCount = args.state?.tryCount ?? 0;
125
125
  const revealed = args.state?.revealed === true;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Formative delivery vocabulary.
2
+ * Item session control vocabulary.
3
3
  *
4
4
  * A **Try** is one submitted-for-checking pass over a single item. It is not
5
5
  * `TestAttemptSession` (the assessment administration) and not
@@ -7,11 +7,11 @@
7
7
  * an item). Both of those already own the word "attempt" in this codebase, at
8
8
  * two different scopes, which is why this contract does not use it.
9
9
  *
10
- * See `docs/prds/formative-delivery-contract.md` for the ratified contract and
10
+ * See `docs/prds/item-session-control-contract.md` for the ratified contract and
11
11
  * its QTI 3 mapping.
12
12
  */
13
13
  /** How many Tries a learner gets on one item. */
14
- export type FormativeTryLimit = number | "unlimited";
14
+ export type TryLimit = number | "unlimited";
15
15
  /**
16
16
  * What the learner sees after a Try.
17
17
  *
@@ -20,54 +20,52 @@ export type FormativeTryLimit = number | "unlimited";
20
20
  * `role: "instructor"`, which is the element convention for additionally
21
21
  * revealing the authored correct response.
22
22
  */
23
- export type FormativeFeedbackReveal = "none" | "correctness" | "solution";
23
+ export type FeedbackReveal = "none" | "correctness" | "solution";
24
24
  /** When a reveal happens: after every Try, or only once Tries are spent. */
25
- export type FormativeRevealTiming = "on-try" | "on-final-try";
25
+ export type FeedbackRevealTiming = "on-try" | "on-final-try";
26
26
  /**
27
- * Authored policy. Lives on `AssessmentSection.formative` as the section
28
- * default and on `AssessmentItemRef.formative` as a per-item override.
27
+ * Authored policy. Lives on `AssessmentSection.itemSessionControl` as the section
28
+ * default and on `AssessmentItemRef.itemSessionControl` as a per-item override.
29
29
  */
30
- export interface FormativeDeliveryPolicy {
30
+ export interface ItemSessionControlPolicy {
31
31
  /**
32
32
  * Absent or `false` leaves delivery exactly as it is without this contract:
33
33
  * no control, no projection, no state.
34
34
  */
35
35
  enabled?: boolean;
36
36
  /** Default 1. */
37
- maxTries?: FormativeTryLimit;
37
+ maxTries?: TryLimit;
38
38
  /** Default `"correctness"`. */
39
- feedback?: FormativeFeedbackReveal;
39
+ feedback?: FeedbackReveal;
40
40
  /** Default `"on-try"`. */
41
- revealOn?: FormativeRevealTiming;
41
+ revealOn?: FeedbackRevealTiming;
42
42
  }
43
- /** Same shape as the section policy; every field overrides independently. */
44
- export type FormativeItemPolicy = FormativeDeliveryPolicy;
45
43
  /** The policy after built-in defaults, section, and item ref are merged. */
46
- export interface ResolvedFormativePolicy {
44
+ export interface ResolvedItemSessionControlPolicy {
47
45
  enabled: boolean;
48
- maxTries: FormativeTryLimit;
49
- feedback: FormativeFeedbackReveal;
50
- revealOn: FormativeRevealTiming;
46
+ maxTries: TryLimit;
47
+ feedback: FeedbackReveal;
48
+ revealOn: FeedbackRevealTiming;
51
49
  }
52
50
  /**
53
51
  * `"unknown"` is the honest state for an item no loaded controller can score —
54
52
  * one holding a rubric element, or one whose element bundle exposes no
55
53
  * `outcome`. It is never collapsed into `"incorrect"`.
56
54
  */
57
- export type FormativeCorrectness = "correct" | "partial" | "incorrect" | "unknown";
55
+ export type TryCorrectness = "correct" | "partial" | "incorrect" | "unknown";
58
56
  /**
59
57
  * The subset of an element outcome that aggregation reads. `OutcomeResponse` is
60
58
  * assignable to this; the structural type keeps this module free of a
61
59
  * dependency on the entity types, which import policy types from here.
62
60
  */
63
- export interface FormativeScoredOutcome {
61
+ export interface ScoredElementOutcome {
64
62
  score?: number;
65
63
  max?: number;
66
64
  [key: string]: unknown;
67
65
  }
68
66
  /** The recorded result of one Try. */
69
- export interface FormativeTryOutcome {
70
- correctness: FormativeCorrectness;
67
+ export interface TryOutcome {
68
+ correctness: TryCorrectness;
71
69
  points?: number;
72
70
  max?: number;
73
71
  scoredElementCount: number;
@@ -84,10 +82,10 @@ export interface FormativeTryOutcome {
84
82
  * A trade: this persists inside the session slice, so a snapshot grows by
85
83
  * whatever the elements put in their outcomes — some include a scoring trace.
86
84
  */
87
- elementOutcomes?: FormativeScoredOutcome[];
85
+ elementOutcomes?: ScoredElementOutcome[];
88
86
  }
89
- /** Per-item delivery state. Persisted; see `FormativeSectionSlice`. */
90
- export interface FormativeItemState {
87
+ /** Per-item delivery state. Persisted; see `TrySectionSlice`. */
88
+ export interface ItemTryState {
91
89
  version: 1;
92
90
  itemIdentifier: string;
93
91
  tryCount: number;
@@ -98,7 +96,7 @@ export interface FormativeItemState {
98
96
  * reload restores the screen the learner left.
99
97
  */
100
98
  revealed: boolean;
101
- lastOutcome?: FormativeTryOutcome;
99
+ lastOutcome?: TryOutcome;
102
100
  /** 1-based Try on which the item first scored full credit. Never overwritten. */
103
101
  firstCorrectTry?: number;
104
102
  /**
@@ -106,19 +104,19 @@ export interface FormativeItemState {
106
104
  * than the learner earning it. Overrides the policy's `feedback` for the env
107
105
  * projection only — the policy still decides Tries.
108
106
  *
109
- * Set by `revealFormativeItem`, cleared by `hideFormativeItem` and by a
107
+ * Set by `revealItemFeedback`, cleared by `hideItemFeedback` and by a
110
108
  * learner retry, so a teacher-driven "show the answer" does not silently
111
109
  * upgrade every later reveal on that item.
112
110
  */
113
- revealOverride?: FormativeFeedbackReveal;
111
+ revealOverride?: FeedbackReveal;
114
112
  }
115
- /** The persisted slice, carried on `SectionControllerSessionState.formative`. */
116
- export interface FormativeSectionSlice {
113
+ /** The persisted slice, carried on `SectionControllerSessionState.tries`. */
114
+ export interface TrySectionSlice {
117
115
  version: 1;
118
- items: Record<string, FormativeItemState>;
116
+ items: Record<string, ItemTryState>;
119
117
  }
120
118
  /** Projected over the section env for one revealed item. */
121
- export interface FormativeEnvOverride {
119
+ export interface FeedbackEnvOverride {
122
120
  mode: "evaluate";
123
121
  role: "student" | "instructor";
124
122
  }
@@ -126,18 +124,18 @@ export interface FormativeEnvOverride {
126
124
  * What a rendering component needs, derived once so no component reimplements
127
125
  * the predicate. Carries no copy — wording belongs to the rendering package.
128
126
  */
129
- export interface FormativeItemView {
127
+ export interface ItemTryView {
130
128
  enabled: boolean;
131
129
  tryCount: number;
132
130
  triesRemaining: number | "unlimited";
133
131
  canCheck: boolean;
134
132
  canRetry: boolean;
135
133
  revealed: boolean;
136
- envOverride?: FormativeEnvOverride;
137
- lastOutcome?: FormativeTryOutcome;
134
+ envOverride?: FeedbackEnvOverride;
135
+ lastOutcome?: TryOutcome;
138
136
  }
139
137
  /** Section rollup over Try outcomes. */
140
- export interface FormativeMasteryRollup {
138
+ export interface MasteryRollup {
141
139
  version: 1;
142
140
  totalItems: number;
143
141
  /**
@@ -153,12 +151,12 @@ export interface FormativeMasteryRollup {
153
151
  complete: boolean;
154
152
  }
155
153
  /** The composition-model projection layouts read. */
156
- export interface FormativeSectionProjection {
154
+ export interface TrySectionProjection {
157
155
  version: 1;
158
156
  enabled: boolean;
159
- policies: Record<string, ResolvedFormativePolicy>;
160
- states: Record<string, FormativeItemState>;
161
- mastery: FormativeMasteryRollup;
157
+ policies: Record<string, ResolvedItemSessionControlPolicy>;
158
+ states: Record<string, ItemTryState>;
159
+ mastery: MasteryRollup;
162
160
  }
163
161
  /** The two learner actions a rendering component can request. */
164
- export type FormativeAction = "check" | "retry";
162
+ export type TryAction = "check" | "retry";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Formative delivery vocabulary.
2
+ * Item session control vocabulary.
3
3
  *
4
4
  * A **Try** is one submitted-for-checking pass over a single item. It is not
5
5
  * `TestAttemptSession` (the assessment administration) and not
@@ -7,7 +7,7 @@
7
7
  * an item). Both of those already own the word "attempt" in this codebase, at
8
8
  * two different scopes, which is why this contract does not use it.
9
9
  *
10
- * See `docs/prds/formative-delivery-contract.md` for the ratified contract and
10
+ * See `docs/prds/item-session-control-contract.md` for the ratified contract and
11
11
  * its QTI 3 mapping.
12
12
  */
13
13
  export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Hostname classification for a URL a server fetches on someone else's behalf,
3
+ * such as an SSML `<audio src>` a TTS provider will request or an asset URL an
4
+ * upstream service returns. Every such check reads this module, so no two
5
+ * copies of it can drift apart.
6
+ *
7
+ * IP literals are classified by `ipaddr.js`, whose ranges follow the IANA IPv4
8
+ * and IPv6 Special-Purpose Address Registries (RFC 6890). A host is private
9
+ * unless it is a public unicast address or a name: loopback, private, link-local,
10
+ * unique-local, carrier-grade NAT, multicast, broadcast, documentation and
11
+ * reserved ranges, and the IPv6 forms that embed an IPv4 address (NAT64, 6to4,
12
+ * Teredo), all count. `ipaddr.js` also reads the numeric IPv4 forms (`2130706433`,
13
+ * `0x7f000001`, `0177.0.0.1`) and unmaps IPv4-mapped IPv6.
14
+ *
15
+ * Only the literal is checked. A public name that resolves to a private address
16
+ * passes; guarding that takes a check of the resolved address at connect time.
17
+ *
18
+ * @module
19
+ */
20
+ /** Whether `hostname` is a cloud instance-metadata endpoint. */
21
+ export declare function isCloudMetadataHostname(hostname: string): boolean;
22
+ /**
23
+ * Whether `hostname` is anything other than a public unicast address or a
24
+ * public name: `localhost` and its subdomains (RFC 6761), or an IP literal in
25
+ * any special-purpose range.
26
+ */
27
+ export declare function isPrivateHostname(hostname: string): boolean;