@intellectif/lk-core 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +12 -4
  2. package/dist/{activity-wkzRemHx.d.cts → activity-gelWNZ6V.d.cts} +49 -10
  3. package/dist/{activity-wkzRemHx.d.ts → activity-gelWNZ6V.d.ts} +49 -10
  4. package/dist/{chunk-WV5WQ3SZ.js → chunk-2SQ75JTE.js} +2 -2
  5. package/dist/{chunk-4JR3UXX6.cjs → chunk-5RE3ZRSA.cjs} +8 -1
  6. package/dist/chunk-5RE3ZRSA.cjs.map +1 -0
  7. package/dist/{chunk-FCM5VJBS.cjs → chunk-7NIH5IL3.cjs} +16 -13
  8. package/dist/chunk-7NIH5IL3.cjs.map +1 -0
  9. package/dist/{chunk-R7PDJBRX.cjs → chunk-AFIQQADJ.cjs} +4 -4
  10. package/dist/{chunk-R7PDJBRX.cjs.map → chunk-AFIQQADJ.cjs.map} +1 -1
  11. package/dist/{chunk-SM5HUGYU.cjs → chunk-MVZKEWZN.cjs} +21 -11
  12. package/dist/chunk-MVZKEWZN.cjs.map +1 -0
  13. package/dist/{chunk-DUQVGLQ3.js → chunk-NOBJYDOB.js} +15 -5
  14. package/dist/chunk-NOBJYDOB.js.map +1 -0
  15. package/dist/{chunk-LSHDNA2T.js → chunk-XL75ZZVM.js} +6 -3
  16. package/dist/chunk-XL75ZZVM.js.map +1 -0
  17. package/dist/{chunk-NUCEUU4P.js → chunk-YCXIHFLG.js} +8 -1
  18. package/dist/chunk-YCXIHFLG.js.map +1 -0
  19. package/dist/{index-BKyZrd94.d.cts → index-B_RLyeEj.d.ts} +101 -14
  20. package/dist/{index-CLmXzBhB.d.ts → index-CDWH2WIg.d.cts} +101 -14
  21. package/dist/index.cjs +336 -25
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +360 -6
  24. package/dist/index.d.ts +360 -6
  25. package/dist/index.js +317 -6
  26. package/dist/index.js.map +1 -1
  27. package/dist/schemas.cjs +3 -3
  28. package/dist/schemas.d.cts +2 -2
  29. package/dist/schemas.d.ts +2 -2
  30. package/dist/schemas.js +2 -2
  31. package/dist/scoring.cjs +3 -3
  32. package/dist/scoring.d.cts +2 -2
  33. package/dist/scoring.d.ts +2 -2
  34. package/dist/scoring.js +2 -2
  35. package/dist/xapi.cjs +3 -3
  36. package/dist/xapi.d.cts +1 -1
  37. package/dist/xapi.d.ts +1 -1
  38. package/dist/xapi.js +2 -2
  39. package/package.json +1 -1
  40. package/dist/chunk-4JR3UXX6.cjs.map +0 -1
  41. package/dist/chunk-DUQVGLQ3.js.map +0 -1
  42. package/dist/chunk-FCM5VJBS.cjs.map +0 -1
  43. package/dist/chunk-LSHDNA2T.js.map +0 -1
  44. package/dist/chunk-NUCEUU4P.js.map +0 -1
  45. package/dist/chunk-SM5HUGYU.cjs.map +0 -1
  46. /package/dist/{chunk-WV5WQ3SZ.js.map → chunk-2SQ75JTE.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
3
 
4
4
 
@@ -10,14 +10,14 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkSM5HUGYUcjs = require('./chunk-SM5HUGYU.cjs');
13
+ var _chunkMVZKEWZNcjs = require('./chunk-MVZKEWZN.cjs');
14
14
 
15
15
 
16
16
 
17
17
 
18
18
 
19
19
 
20
- var _chunkR7PDJBRXcjs = require('./chunk-R7PDJBRX.cjs');
20
+ var _chunkAFIQQADJcjs = require('./chunk-AFIQQADJ.cjs');
21
21
 
22
22
 
23
23
 
@@ -31,7 +31,7 @@ var _chunkR7PDJBRXcjs = require('./chunk-R7PDJBRX.cjs');
31
31
 
32
32
 
33
33
 
34
- var _chunkFCM5VJBScjs = require('./chunk-FCM5VJBS.cjs');
34
+ var _chunk7NIH5IL3cjs = require('./chunk-7NIH5IL3.cjs');
35
35
 
36
36
 
37
37
 
@@ -63,7 +63,63 @@ var _chunkFCM5VJBScjs = require('./chunk-FCM5VJBS.cjs');
63
63
 
64
64
 
65
65
 
66
- var _chunk4JR3UXX6cjs = require('./chunk-4JR3UXX6.cjs');
66
+ var _chunk5RE3ZRSAcjs = require('./chunk-5RE3ZRSA.cjs');
67
+
68
+ // src/content-hash.ts
69
+ function canonicalJson(value, seen = /* @__PURE__ */ new Set()) {
70
+ if (value === null) {
71
+ return "null";
72
+ }
73
+ if (typeof value === "number") {
74
+ return Number.isFinite(value) ? JSON.stringify(value === 0 ? 0 : value) : `"#${String(value)}"`;
75
+ }
76
+ if (typeof value === "string" || typeof value === "boolean") {
77
+ return JSON.stringify(value);
78
+ }
79
+ if (typeof value === "bigint") {
80
+ return `"#${value.toString()}n"`;
81
+ }
82
+ if (typeof value === "object") {
83
+ if (seen.has(value)) {
84
+ throw new Error(
85
+ "canonicalJson: the value contains a circular reference and cannot be fingerprinted."
86
+ );
87
+ }
88
+ seen.add(value);
89
+ try {
90
+ if (Array.isArray(value)) {
91
+ return `[${value.map((element) => element === void 0 ? "null" : canonicalJson(element, seen)).join(",")}]`;
92
+ }
93
+ const source = value;
94
+ const parts = [];
95
+ for (const key of Object.keys(source).sort()) {
96
+ const entry = source[key];
97
+ if (entry === void 0) {
98
+ continue;
99
+ }
100
+ parts.push(`${JSON.stringify(key)}:${canonicalJson(entry, seen)}`);
101
+ }
102
+ return `{${parts.join(",")}}`;
103
+ } finally {
104
+ seen.delete(value);
105
+ }
106
+ }
107
+ return "null";
108
+ }
109
+ var FNV_OFFSET = 14695981039346656037n;
110
+ var FNV_PRIME = 1099511628211n;
111
+ var MASK64 = (1n << 64n) - 1n;
112
+ function fingerprint(input) {
113
+ const bytes = new TextEncoder().encode(input);
114
+ let hash = FNV_OFFSET;
115
+ for (const byte of bytes) {
116
+ hash = (hash ^ BigInt(byte)) * FNV_PRIME & MASK64;
117
+ }
118
+ return hash.toString(16).padStart(16, "0");
119
+ }
120
+ function contentHash(value) {
121
+ return fingerprint(canonicalJson(value));
122
+ }
67
123
 
68
124
  // src/shuffle.ts
69
125
  function hashSeed(input) {
@@ -92,6 +148,23 @@ function seededShuffle(items, seed, options = {}) {
92
148
  function isItemGroup(entry) {
93
149
  return entry.type === "item-group";
94
150
  }
151
+ function keyOf(entry) {
152
+ const key = entry.slotKey;
153
+ if (key === void 0) {
154
+ return void 0;
155
+ }
156
+ if (typeof key !== "string" || key.length === 0) {
157
+ throw new Error(
158
+ `flattenSequence: slotKey must be a non-empty string, received ${String(key)}.`
159
+ );
160
+ }
161
+ if (key.includes(".")) {
162
+ throw new Error(
163
+ `flattenSequence: slotKey "${key}" contains a "." , which separates a group from its item in a slot id. Choose a key without it, or the two become indistinguishable.`
164
+ );
165
+ }
166
+ return key;
167
+ }
95
168
  function flattenSequence(entries, options = {}) {
96
169
  const shuffleEntries = options.shuffleEntries === true;
97
170
  const needsSeed = shuffleEntries || entries.some((entry) => isItemGroup(entry) && entry.shuffle === "within-group");
@@ -105,8 +178,9 @@ function flattenSequence(entries, options = {}) {
105
178
  const ordered = shuffleEntries ? seededShuffle(authored, `${seed}:entries`) : authored;
106
179
  const slots = [];
107
180
  for (const { entry, entryIndex } of ordered) {
181
+ const entryKey = _nullishCoalesce(keyOf(entry), () => ( String(entryIndex)));
108
182
  if (!isItemGroup(entry)) {
109
- slots.push({ slotId: String(entryIndex), index: slots.length, activity: entry });
183
+ slots.push({ slotId: entryKey, index: slots.length, activity: entry });
110
184
  continue;
111
185
  }
112
186
  if (entry.items.length === 0) {
@@ -119,7 +193,7 @@ function flattenSequence(entries, options = {}) {
119
193
  const size = presented.length;
120
194
  presented.forEach(({ item, itemIndex }, position) => {
121
195
  slots.push({
122
- slotId: `${entryIndex}.${itemIndex}`,
196
+ slotId: `${entryKey}.${_nullishCoalesce(keyOf(item), () => ( String(itemIndex)))}`,
123
197
  index: slots.length,
124
198
  activity: item,
125
199
  group: {
@@ -132,9 +206,234 @@ function flattenSequence(entries, options = {}) {
132
206
  });
133
207
  });
134
208
  }
209
+ const seenSlotIds = /* @__PURE__ */ new Set();
210
+ const seenEntryKeys = /* @__PURE__ */ new Set();
211
+ for (const slot of slots) {
212
+ if (seenSlotIds.has(slot.slotId)) {
213
+ throw new Error(
214
+ `flattenSequence: duplicate slot id "${slot.slotId}". Two entries declare the same slotKey, so responses stored against them could not be told apart.`
215
+ );
216
+ }
217
+ seenSlotIds.add(slot.slotId);
218
+ }
219
+ for (const { entry, entryIndex } of ordered) {
220
+ const entryKey = _nullishCoalesce(keyOf(entry), () => ( String(entryIndex)));
221
+ if (seenEntryKeys.has(entryKey)) {
222
+ throw new Error(
223
+ `flattenSequence: duplicate entry key "${entryKey}". A loose activity and an item group cannot share a slotKey \u2014 their slot ids would not collide, but everything that reads the entry they belong to would treat them as one entry.`
224
+ );
225
+ }
226
+ seenEntryKeys.add(entryKey);
227
+ }
135
228
  return slots;
136
229
  }
137
230
 
231
+ // src/attempt-plan.ts
232
+ function contentOf(activity) {
233
+ if (!Object.hasOwn(activity, "slotKey")) {
234
+ return activity;
235
+ }
236
+ const { slotKey: _slotKey, ...content } = activity;
237
+ return content;
238
+ }
239
+ function planSlot(slot, points) {
240
+ if (!Number.isFinite(points) || points < 0) {
241
+ throw new Error(
242
+ `planAttempt: slot "${slot.slotId}" resolved to ${String(points)} points. Points must be a finite, non-negative number, or the paper has no defensible total.`
243
+ );
244
+ }
245
+ return {
246
+ slotId: slot.slotId,
247
+ index: slot.index,
248
+ activityId: slot.activity.id,
249
+ activityType: slot.activity.type,
250
+ points,
251
+ contentHash: contentHash(contentOf(slot.activity)),
252
+ ...slot.group !== void 0 ? {
253
+ group: {
254
+ id: slot.group.id,
255
+ ...slot.group.title !== void 0 ? { title: slot.group.title } : {},
256
+ stimulusHash: contentHash(slot.group.stimulus)
257
+ }
258
+ } : {}
259
+ };
260
+ }
261
+ function planAttempt(entries, options = {}) {
262
+ const { seed, shuffleEntries, points } = options;
263
+ const slots = flattenSequence(entries, {
264
+ ...shuffleEntries !== void 0 ? { shuffleEntries } : {},
265
+ ...seed !== void 0 ? { seed } : {}
266
+ });
267
+ const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall', _ => _(slot)]), () => ( 1))));
268
+ const totalPoints = planned.reduce((sum, slot) => sum + slot.points, 0);
269
+ return {
270
+ planVersion: "1.0",
271
+ ...seed !== void 0 ? { seed } : {},
272
+ ...shuffleEntries !== void 0 ? { shuffleEntries } : {},
273
+ // The plan's own fingerprint covers the slots verbatim — identity, order,
274
+ // points and content hashes — so one stored value answers "is this still
275
+ // the paper that was sat?" and the per-slot hashes then say what moved.
276
+ planHash: contentHash(planned),
277
+ slots: planned,
278
+ totalPoints
279
+ };
280
+ }
281
+ function verifyAttemptPlan(plan, current) {
282
+ const before = new Map(plan.slots.map((slot) => [slot.slotId, slot]));
283
+ const after = new Map(current.slots.map((slot) => [slot.slotId, slot]));
284
+ const missingSlotIds = plan.slots.filter((s) => !after.has(s.slotId)).map((s) => s.slotId);
285
+ const addedSlotIds = current.slots.filter((s) => !before.has(s.slotId)).map((s) => s.slotId);
286
+ const changedSlotIds = [];
287
+ const changedStimulusSlotIds = [];
288
+ const changedPointsSlotIds = [];
289
+ const reorderedSlotIds = [];
290
+ for (const slot of plan.slots) {
291
+ const now = after.get(slot.slotId);
292
+ if (now === void 0) {
293
+ continue;
294
+ }
295
+ if (now.contentHash !== slot.contentHash) {
296
+ changedSlotIds.push(slot.slotId);
297
+ }
298
+ if (_optionalChain([now, 'access', _2 => _2.group, 'optionalAccess', _3 => _3.stimulusHash]) !== _optionalChain([slot, 'access', _4 => _4.group, 'optionalAccess', _5 => _5.stimulusHash])) {
299
+ changedStimulusSlotIds.push(slot.slotId);
300
+ }
301
+ if (now.points !== slot.points) {
302
+ changedPointsSlotIds.push(slot.slotId);
303
+ }
304
+ if (now.index !== slot.index) {
305
+ reorderedSlotIds.push(slot.slotId);
306
+ }
307
+ }
308
+ return {
309
+ matches: missingSlotIds.length === 0 && addedSlotIds.length === 0 && changedSlotIds.length === 0 && changedStimulusSlotIds.length === 0 && changedPointsSlotIds.length === 0 && reorderedSlotIds.length === 0,
310
+ missingSlotIds,
311
+ addedSlotIds,
312
+ changedSlotIds,
313
+ changedStimulusSlotIds,
314
+ changedPointsSlotIds,
315
+ reorderedSlotIds
316
+ };
317
+ }
318
+ function missingOutcome(slot, policy) {
319
+ if (typeof policy === "function") {
320
+ return policy(slot);
321
+ }
322
+ if (policy === "zero") {
323
+ return { status: "scored", score: 0, maxScore: 1, passed: false, feedback: null, details: [] };
324
+ }
325
+ return { status: "deferred", reason: "no_response_recorded", maxScore: 1 };
326
+ }
327
+ function scoredItemsFromPlan(plan, outcomes, options = {}) {
328
+ const policy = _nullishCoalesce(options.missing, () => ( "deferred"));
329
+ return plan.slots.map((slot) => ({
330
+ slotId: slot.slotId,
331
+ activityId: slot.activityId,
332
+ points: slot.points,
333
+ // `Object.hasOwn`, not a bare lookup: slot ids come from authored
334
+ // `slotKey`s, and a key of `constructor` or `toString` would otherwise
335
+ // resolve through the prototype chain and hand a FUNCTION to the scorer
336
+ // in place of an outcome.
337
+ outcome: Object.hasOwn(outcomes, slot.slotId) ? outcomes[slot.slotId] : missingOutcome(slot, policy)
338
+ }));
339
+ }
340
+
341
+ // src/attempt-state.ts
342
+ function cloneResponses(responses) {
343
+ return typeof structuredClone === "function" ? structuredClone(responses) : JSON.parse(JSON.stringify(responses));
344
+ }
345
+ function unknownKeys(plan, keys) {
346
+ const known = new Set(plan.slots.map((slot) => slot.slotId));
347
+ return keys.filter((key) => !known.has(key));
348
+ }
349
+ function serializeAttemptState(plan, progress) {
350
+ const responseKeys = Object.keys(progress.responses);
351
+ const submittedSlotIds = [..._nullishCoalesce(progress.submittedSlotIds, () => ( []))];
352
+ const strayResponses = unknownKeys(plan, responseKeys);
353
+ if (strayResponses.length > 0) {
354
+ throw new Error(
355
+ `serializeAttemptState: response recorded for slot(s) the plan does not contain: ${strayResponses.join(", ")}. A response that belongs to no question cannot be scored and would be lost silently.`
356
+ );
357
+ }
358
+ const straySubmitted = unknownKeys(plan, submittedSlotIds);
359
+ if (straySubmitted.length > 0) {
360
+ throw new Error(
361
+ `serializeAttemptState: submitted slot(s) the plan does not contain: ${straySubmitted.join(", ")}.`
362
+ );
363
+ }
364
+ const index = _nullishCoalesce(progress.index, () => ( 0));
365
+ const lastIndex = Math.max(0, plan.slots.length - 1);
366
+ if (!Number.isInteger(index) || index < 0 || index > lastIndex) {
367
+ throw new Error(
368
+ `serializeAttemptState: index ${String(index)} is not a position in a ${plan.slots.length}-slot plan.`
369
+ );
370
+ }
371
+ return {
372
+ stateVersion: "1.0",
373
+ planHash: plan.planHash,
374
+ // Copied DEEPLY, not aliased: a snapshot that keeps mutating with the
375
+ // live attempt is not a snapshot. See cloneResponses.
376
+ responses: cloneResponses(progress.responses),
377
+ submittedSlotIds,
378
+ index,
379
+ ...progress.savedAt !== void 0 ? { savedAt: progress.savedAt } : {}
380
+ };
381
+ }
382
+ function restoreAttemptState(plan, state) {
383
+ if (state === null || typeof state !== "object") {
384
+ throw new Error("restoreAttemptState: the snapshot is not an object.");
385
+ }
386
+ if (state.stateVersion !== "1.0") {
387
+ throw new Error(
388
+ `restoreAttemptState: unsupported stateVersion ${JSON.stringify(state.stateVersion)}. This build understands "1.0"; a newer snapshot must be migrated before it is restored.`
389
+ );
390
+ }
391
+ if (state.responses === null || typeof state.responses !== "object") {
392
+ throw new Error(
393
+ "restoreAttemptState: the snapshot carries no responses object (a NULL column, or a partially written row)."
394
+ );
395
+ }
396
+ if (state.planHash !== plan.planHash) {
397
+ throw new Error(
398
+ `restoreAttemptState: this snapshot belongs to a different paper (snapshot ${state.planHash}, plan ${plan.planHash}). Restoring it would attach the learner's answers to questions they never saw.`
399
+ );
400
+ }
401
+ return serializeAttemptState(plan, {
402
+ responses: state.responses,
403
+ submittedSlotIds: state.submittedSlotIds,
404
+ index: state.index,
405
+ ...state.savedAt !== void 0 ? { savedAt: state.savedAt } : {}
406
+ });
407
+ }
408
+ function diffResponses(before, after) {
409
+ const slotIds = [.../* @__PURE__ */ new Set([...Object.keys(before.responses), ...Object.keys(after.responses)])];
410
+ slotIds.sort();
411
+ const entries = [];
412
+ for (const slotId of slotIds) {
413
+ const had = Object.hasOwn(before.responses, slotId);
414
+ const has = Object.hasOwn(after.responses, slotId);
415
+ const from = before.responses[slotId];
416
+ const to = after.responses[slotId];
417
+ if (had && !has) {
418
+ entries.push({ slotId, change: "removed", ...from !== void 0 ? { before: from } : {} });
419
+ continue;
420
+ }
421
+ if (!had && has) {
422
+ entries.push({ slotId, change: "added", ...to !== void 0 ? { after: to } : {} });
423
+ continue;
424
+ }
425
+ if (canonicalJson(from) !== canonicalJson(to)) {
426
+ entries.push({
427
+ slotId,
428
+ change: "changed",
429
+ ...from !== void 0 ? { before: from } : {},
430
+ ...to !== void 0 ? { after: to } : {}
431
+ });
432
+ }
433
+ }
434
+ return entries;
435
+ }
436
+
138
437
  // src/redact.ts
139
438
  function mergePolicy(base, overrides) {
140
439
  if (overrides === void 0) {
@@ -188,9 +487,9 @@ function redactValue(value, policy, reveal) {
188
487
  }
189
488
  function redact(data, options = {}) {
190
489
  const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
191
- const descriptor = _chunk4JR3UXX6cjs.getActivityTypeDescriptor.call(void 0, data.type);
490
+ const descriptor = _chunk5RE3ZRSAcjs.getActivityTypeDescriptor.call(void 0, data.type);
192
491
  if (descriptor === void 0) {
193
- throw new (0, _chunk4JR3UXX6cjs.UnknownActivityTypeError)(String(data.type));
492
+ throw new (0, _chunk5RE3ZRSAcjs.UnknownActivityTypeError)(String(data.type));
194
493
  }
195
494
  if (descriptor.fieldPolicy === void 0) {
196
495
  throw new Error(
@@ -203,7 +502,7 @@ function redact(data, options = {}) {
203
502
  if (reveal === "none" && descriptor.redactedSchema !== void 0) {
204
503
  const parsed = descriptor.redactedSchema.safeParse(result);
205
504
  if (!parsed.success) {
206
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(
505
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(
207
506
  descriptor.type,
208
507
  parsed.error.issues.map((issue) => ({
209
508
  path: issue.path.map(String),
@@ -217,13 +516,13 @@ function redact(data, options = {}) {
217
516
  }
218
517
  function assertRedacted(data) {
219
518
  if (typeof data !== "object" || data === null) {
220
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)("unknown", [
519
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)("unknown", [
221
520
  { path: [], message: "Redacted activity data must be an object.", code: "invalid_type" }
222
521
  ]);
223
522
  }
224
523
  const candidate = data;
225
524
  if (candidate.redacted !== true) {
226
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
525
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
227
526
  {
228
527
  path: ["redacted"],
229
528
  message: "Missing redacted marker \u2014 this payload is not a redact() projection.",
@@ -232,12 +531,12 @@ function assertRedacted(data) {
232
531
  ]);
233
532
  }
234
533
  const type = typeof candidate.type === "string" ? candidate.type : "";
235
- const descriptor = _chunk4JR3UXX6cjs.getActivityTypeDescriptor.call(void 0, type);
534
+ const descriptor = _chunk5RE3ZRSAcjs.getActivityTypeDescriptor.call(void 0, type);
236
535
  if (descriptor === void 0) {
237
- throw new (0, _chunk4JR3UXX6cjs.UnknownActivityTypeError)(type);
536
+ throw new (0, _chunk5RE3ZRSAcjs.UnknownActivityTypeError)(type);
238
537
  }
239
538
  if (descriptor.redactedSchema === void 0) {
240
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(descriptor.type, [
539
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(descriptor.type, [
241
540
  {
242
541
  path: [],
243
542
  message: `Activity type "${descriptor.type}" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,
@@ -247,7 +546,7 @@ function assertRedacted(data) {
247
546
  }
248
547
  const parsed = descriptor.redactedSchema.safeParse(candidate);
249
548
  if (!parsed.success) {
250
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(
549
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(
251
550
  descriptor.type,
252
551
  parsed.error.issues.map((issue) => ({
253
552
  path: issue.path.map(String),
@@ -273,6 +572,9 @@ var ITEM_GROUP_FIELD_POLICY = {
273
572
  type: "public",
274
573
  id: "public",
275
574
  title: "public",
575
+ // See the note on the built-in activity policies: a slot key is identity,
576
+ // and identity has to cross the redaction boundary intact.
577
+ slotKey: "public",
276
578
  shuffle: "public",
277
579
  stimulus: STIMULUS_FIELD_POLICY
278
580
  };
@@ -286,9 +588,9 @@ function redactItemGroup(group, options = {}) {
286
588
  redacted: true
287
589
  };
288
590
  if (reveal === "none") {
289
- const parsed = _chunkFCM5VJBScjs.RedactedItemGroupSchema.safeParse(result);
591
+ const parsed = _chunk7NIH5IL3cjs.RedactedItemGroupSchema.safeParse(result);
290
592
  if (!parsed.success) {
291
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(
593
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(
292
594
  "item-group",
293
595
  parsed.error.issues.map((issue) => ({
294
596
  path: issue.path.map(String),
@@ -302,13 +604,13 @@ function redactItemGroup(group, options = {}) {
302
604
  }
303
605
  function assertRedactedItemGroup(data) {
304
606
  if (typeof data !== "object" || data === null) {
305
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)("item-group", [
607
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)("item-group", [
306
608
  { path: [], message: "Redacted item group must be an object.", code: "invalid_type" }
307
609
  ]);
308
610
  }
309
611
  const candidate = data;
310
612
  if (candidate.redacted !== true) {
311
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)("item-group", [
613
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)("item-group", [
312
614
  {
313
615
  path: ["redacted"],
314
616
  message: "Missing redacted marker \u2014 this payload is not a redactItemGroup() projection.",
@@ -316,9 +618,9 @@ function assertRedactedItemGroup(data) {
316
618
  }
317
619
  ]);
318
620
  }
319
- const parsed = _chunkFCM5VJBScjs.RedactedItemGroupSchema.safeParse(candidate);
621
+ const parsed = _chunk7NIH5IL3cjs.RedactedItemGroupSchema.safeParse(candidate);
320
622
  if (!parsed.success) {
321
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(
623
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(
322
624
  "item-group",
323
625
  parsed.error.issues.map((issue) => ({
324
626
  path: issue.path.map(String),
@@ -331,8 +633,8 @@ function assertRedactedItemGroup(data) {
331
633
  try {
332
634
  assertRedacted(item);
333
635
  } catch (error) {
334
- if (error instanceof _chunk4JR3UXX6cjs.ActivitySchemaError) {
335
- throw new (0, _chunk4JR3UXX6cjs.ActivitySchemaError)(
636
+ if (error instanceof _chunk5RE3ZRSAcjs.ActivitySchemaError) {
637
+ throw new (0, _chunk5RE3ZRSAcjs.ActivitySchemaError)(
336
638
  "item-group",
337
639
  error.errors.map((issue) => ({
338
640
  ...issue,
@@ -411,5 +713,14 @@ function assertRedactedItemGroup(data) {
411
713
 
412
714
 
413
715
 
414
- exports.ActivitySchemaError = _chunk4JR3UXX6cjs.ActivitySchemaError; exports.BlankConfigSchema = _chunk4JR3UXX6cjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunkSM5HUGYUcjs.DEFAULT_PASS_THRESHOLD; exports.DeferredScoringError = _chunk4JR3UXX6cjs.DeferredScoringError; exports.FeedbackSchema = _chunk4JR3UXX6cjs.FeedbackSchema; exports.FillInTheBlanksDataSchema = _chunk4JR3UXX6cjs.FillInTheBlanksDataSchema; exports.ItemGroupSchema = _chunkFCM5VJBScjs.ItemGroupSchema; exports.MediaSchema = _chunk4JR3UXX6cjs.MediaSchema; exports.MediaUrlSchema = _chunk4JR3UXX6cjs.MediaUrlSchema; exports.MultipleChoiceDataSchema = _chunk4JR3UXX6cjs.MultipleChoiceDataSchema; exports.MultipleChoiceOptionSchema = _chunk4JR3UXX6cjs.MultipleChoiceOptionSchema; exports.RedactedBlankConfigSchema = _chunk4JR3UXX6cjs.RedactedBlankConfigSchema; exports.RedactedFillInTheBlanksDataSchema = _chunk4JR3UXX6cjs.RedactedFillInTheBlanksDataSchema; exports.RedactedItemGroupSchema = _chunkFCM5VJBScjs.RedactedItemGroupSchema; exports.RedactedMultipleChoiceDataSchema = _chunk4JR3UXX6cjs.RedactedMultipleChoiceDataSchema; exports.RedactedMultipleChoiceOptionSchema = _chunk4JR3UXX6cjs.RedactedMultipleChoiceOptionSchema; exports.RedactedScoringError = _chunk4JR3UXX6cjs.RedactedScoringError; exports.RedactedStimulusSchema = _chunkFCM5VJBScjs.RedactedStimulusSchema; exports.RedactedWrittenResponseDataSchema = _chunk4JR3UXX6cjs.RedactedWrittenResponseDataSchema; exports.StimulusSchema = _chunkFCM5VJBScjs.StimulusSchema; exports.TextMatchPolicySchema = _chunk4JR3UXX6cjs.TextMatchPolicySchema; exports.UnknownActivityTypeError = _chunk4JR3UXX6cjs.UnknownActivityTypeError; exports.WrittenResponseDataSchema = _chunk4JR3UXX6cjs.WrittenResponseDataSchema; exports.WrittenResponseRubricCriterionSchema = _chunk4JR3UXX6cjs.WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = _chunk4JR3UXX6cjs.WrittenResponseRubricSchema; exports.XAPIVerb = _chunkR7PDJBRXcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkR7PDJBRXcjs.XAPI_VERB_DISPLAY; exports.assertRedacted = assertRedacted; exports.assertRedactedItemGroup = assertRedactedItemGroup; exports.classifyBand = _chunkSM5HUGYUcjs.classifyBand; exports.composeAssessmentScore = _chunkSM5HUGYUcjs.composeAssessmentScore; exports.computePassThreshold = _chunkSM5HUGYUcjs.computePassThreshold; exports.countWords = _chunk4JR3UXX6cjs.countWords; exports.defineActivityType = _chunk4JR3UXX6cjs.defineActivityType; exports.evaluate = _chunkSM5HUGYUcjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunkFCM5VJBScjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunk4JR3UXX6cjs.fillInTheBlanksType; exports.flattenSequence = flattenSequence; exports.getActivityTypeDescriptor = _chunk4JR3UXX6cjs.getActivityTypeDescriptor; exports.gradeFromRubric = _chunkSM5HUGYUcjs.gradeFromRubric; exports.gte = _chunkSM5HUGYUcjs.gte; exports.hasGrade = _chunkSM5HUGYUcjs.hasGrade; exports.hashSeed = hashSeed; exports.isItemGroup = isItemGroup; exports.itemGroupJsonSchema = _chunkFCM5VJBScjs.itemGroupJsonSchema; exports.jsonSchemaFor = _chunkFCM5VJBScjs.jsonSchemaFor; exports.levenshteinDistance = _chunk4JR3UXX6cjs.levenshteinDistance; exports.matchText = _chunk4JR3UXX6cjs.matchText; exports.multipleChoiceJsonSchema = _chunkFCM5VJBScjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunk4JR3UXX6cjs.multipleChoiceType; exports.outcomeFromGrade = _chunkSM5HUGYUcjs.outcomeFromGrade; exports.redact = redact; exports.redactItemGroup = redactItemGroup; exports.registerActivityType = _chunk4JR3UXX6cjs.registerActivityType; exports.registeredActivityTypes = _chunk4JR3UXX6cjs.registeredActivityTypes; exports.roundGrade = _chunkSM5HUGYUcjs.roundGrade; exports.score = _chunkSM5HUGYUcjs.score; exports.seededShuffle = seededShuffle; exports.stimulusJsonSchema = _chunkFCM5VJBScjs.stimulusJsonSchema; exports.validateActivity = _chunkFCM5VJBScjs.validateActivity; exports.validateItemGroup = _chunkFCM5VJBScjs.validateItemGroup; exports.validateXAPIStatement = _chunkR7PDJBRXcjs.validateXAPIStatement; exports.writtenResponseJsonSchema = _chunkFCM5VJBScjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunk4JR3UXX6cjs.writtenResponseType; exports.xAPIBuilder = _chunkR7PDJBRXcjs.xAPIBuilder; exports.xapiDefinitionFor = _chunkR7PDJBRXcjs.xapiDefinitionFor;
716
+
717
+
718
+
719
+
720
+
721
+
722
+
723
+
724
+
725
+ exports.ActivitySchemaError = _chunk5RE3ZRSAcjs.ActivitySchemaError; exports.BlankConfigSchema = _chunk5RE3ZRSAcjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunkMVZKEWZNcjs.DEFAULT_PASS_THRESHOLD; exports.DeferredScoringError = _chunk5RE3ZRSAcjs.DeferredScoringError; exports.FeedbackSchema = _chunk5RE3ZRSAcjs.FeedbackSchema; exports.FillInTheBlanksDataSchema = _chunk5RE3ZRSAcjs.FillInTheBlanksDataSchema; exports.ItemGroupSchema = _chunk7NIH5IL3cjs.ItemGroupSchema; exports.MediaSchema = _chunk5RE3ZRSAcjs.MediaSchema; exports.MediaUrlSchema = _chunk5RE3ZRSAcjs.MediaUrlSchema; exports.MultipleChoiceDataSchema = _chunk5RE3ZRSAcjs.MultipleChoiceDataSchema; exports.MultipleChoiceOptionSchema = _chunk5RE3ZRSAcjs.MultipleChoiceOptionSchema; exports.RedactedBlankConfigSchema = _chunk5RE3ZRSAcjs.RedactedBlankConfigSchema; exports.RedactedFillInTheBlanksDataSchema = _chunk5RE3ZRSAcjs.RedactedFillInTheBlanksDataSchema; exports.RedactedItemGroupSchema = _chunk7NIH5IL3cjs.RedactedItemGroupSchema; exports.RedactedMultipleChoiceDataSchema = _chunk5RE3ZRSAcjs.RedactedMultipleChoiceDataSchema; exports.RedactedMultipleChoiceOptionSchema = _chunk5RE3ZRSAcjs.RedactedMultipleChoiceOptionSchema; exports.RedactedScoringError = _chunk5RE3ZRSAcjs.RedactedScoringError; exports.RedactedStimulusSchema = _chunk7NIH5IL3cjs.RedactedStimulusSchema; exports.RedactedWrittenResponseDataSchema = _chunk5RE3ZRSAcjs.RedactedWrittenResponseDataSchema; exports.StimulusSchema = _chunk7NIH5IL3cjs.StimulusSchema; exports.TextMatchPolicySchema = _chunk5RE3ZRSAcjs.TextMatchPolicySchema; exports.UnknownActivityTypeError = _chunk5RE3ZRSAcjs.UnknownActivityTypeError; exports.WrittenResponseDataSchema = _chunk5RE3ZRSAcjs.WrittenResponseDataSchema; exports.WrittenResponseRubricCriterionSchema = _chunk5RE3ZRSAcjs.WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = _chunk5RE3ZRSAcjs.WrittenResponseRubricSchema; exports.XAPIVerb = _chunkAFIQQADJcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkAFIQQADJcjs.XAPI_VERB_DISPLAY; exports.assertRedacted = assertRedacted; exports.assertRedactedItemGroup = assertRedactedItemGroup; exports.canonicalJson = canonicalJson; exports.classifyBand = _chunkMVZKEWZNcjs.classifyBand; exports.composeAssessmentScore = _chunkMVZKEWZNcjs.composeAssessmentScore; exports.computePassThreshold = _chunkMVZKEWZNcjs.computePassThreshold; exports.contentHash = contentHash; exports.countWords = _chunk5RE3ZRSAcjs.countWords; exports.defineActivityType = _chunk5RE3ZRSAcjs.defineActivityType; exports.diffResponses = diffResponses; exports.evaluate = _chunkMVZKEWZNcjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunk7NIH5IL3cjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunk5RE3ZRSAcjs.fillInTheBlanksType; exports.fingerprint = fingerprint; exports.flattenSequence = flattenSequence; exports.getActivityTypeDescriptor = _chunk5RE3ZRSAcjs.getActivityTypeDescriptor; exports.gradeFromRubric = _chunkMVZKEWZNcjs.gradeFromRubric; exports.gte = _chunkMVZKEWZNcjs.gte; exports.hasGrade = _chunkMVZKEWZNcjs.hasGrade; exports.hashSeed = hashSeed; exports.isItemGroup = isItemGroup; exports.itemGroupJsonSchema = _chunk7NIH5IL3cjs.itemGroupJsonSchema; exports.jsonSchemaFor = _chunk7NIH5IL3cjs.jsonSchemaFor; exports.levenshteinDistance = _chunk5RE3ZRSAcjs.levenshteinDistance; exports.matchText = _chunk5RE3ZRSAcjs.matchText; exports.multipleChoiceJsonSchema = _chunk7NIH5IL3cjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunk5RE3ZRSAcjs.multipleChoiceType; exports.outcomeFromGrade = _chunkMVZKEWZNcjs.outcomeFromGrade; exports.planAttempt = planAttempt; exports.redact = redact; exports.redactItemGroup = redactItemGroup; exports.registerActivityType = _chunk5RE3ZRSAcjs.registerActivityType; exports.registeredActivityTypes = _chunk5RE3ZRSAcjs.registeredActivityTypes; exports.restoreAttemptState = restoreAttemptState; exports.roundGrade = _chunkMVZKEWZNcjs.roundGrade; exports.score = _chunkMVZKEWZNcjs.score; exports.scoredItemsFromPlan = scoredItemsFromPlan; exports.seededShuffle = seededShuffle; exports.serializeAttemptState = serializeAttemptState; exports.stimulusJsonSchema = _chunk7NIH5IL3cjs.stimulusJsonSchema; exports.validateActivity = _chunk7NIH5IL3cjs.validateActivity; exports.validateItemGroup = _chunk7NIH5IL3cjs.validateItemGroup; exports.validateXAPIStatement = _chunkAFIQQADJcjs.validateXAPIStatement; exports.verifyAttemptPlan = verifyAttemptPlan; exports.writtenResponseJsonSchema = _chunk7NIH5IL3cjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunk5RE3ZRSAcjs.writtenResponseType; exports.xAPIBuilder = _chunkAFIQQADJcjs.xAPIBuilder; exports.xapiDefinitionFor = _chunkAFIQQADJcjs.xapiDefinitionFor;
415
726
  //# sourceMappingURL=index.cjs.map