@intellectif/lk-core 1.6.0 → 1.8.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/CHANGELOG.md +36 -0
- package/dist/{ai-i3jwXnpX.d.ts → ai-Cnm0qE8v.d.cts} +334 -16
- package/dist/ai-Cnm0qE8v.d.cts.map +1 -0
- package/dist/{ai-i3jwXnpX.d.cts → ai-Cnm0qE8v.d.ts} +334 -16
- package/dist/ai-Cnm0qE8v.d.ts.map +1 -0
- package/dist/ai-check.cjs +88 -7
- package/dist/ai-check.cjs.map +1 -1
- package/dist/ai-check.d.cts +11 -7
- package/dist/ai-check.d.cts.map +1 -1
- package/dist/ai-check.d.ts +11 -7
- package/dist/ai-check.d.ts.map +1 -1
- package/dist/ai-check.js +88 -7
- package/dist/ai-check.js.map +1 -1
- package/dist/{ai-writing-C4YRVrFi.cjs → ai-writing-Bh2Y53cY.cjs} +2567 -203
- package/dist/ai-writing-Bh2Y53cY.cjs.map +1 -0
- package/dist/{ai-writing-OJ5m_1EB.js → ai-writing-DeIV-GfN.js} +2428 -172
- package/dist/ai-writing-DeIV-GfN.js.map +1 -0
- package/dist/{index-Dj92T76o.d.ts → index-CtoPhJAH.d.ts} +2 -8
- package/dist/index-CtoPhJAH.d.ts.map +1 -0
- package/dist/{index--U7hHV0s.d.cts → index-DMh3OYSb.d.cts} +2 -8
- package/dist/index-DMh3OYSb.d.cts.map +1 -0
- package/dist/{index-WBHSrIUU.d.ts → index-HXvg0YRQ.d.ts} +5 -12
- package/dist/index-HXvg0YRQ.d.ts.map +1 -0
- package/dist/{index-CFRgZLhH.d.cts → index-fZ67k-WR.d.cts} +5 -12
- package/dist/index-fZ67k-WR.d.cts.map +1 -0
- package/dist/{index-DeD8EI1D.d.ts → index-g-EWIugp.d.ts} +2 -42
- package/dist/index-g-EWIugp.d.ts.map +1 -0
- package/dist/{index-Uh1u57yq.d.cts → index-oST8GBFa.d.cts} +2 -42
- package/dist/index-oST8GBFa.d.cts.map +1 -0
- package/dist/index.cjs +287 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +227 -71
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +227 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +276 -21
- package/dist/index.js.map +1 -1
- package/dist/{item-group-BbvvH_Ob.js → item-group-BceUoxoM.js} +4 -6
- package/dist/{item-group-BbvvH_Ob.js.map → item-group-BceUoxoM.js.map} +1 -1
- package/dist/{item-group-CQRbb8Rx.cjs → item-group-KV4hYu3a.cjs} +4 -6
- package/dist/{item-group-CQRbb8Rx.cjs.map → item-group-KV4hYu3a.cjs.map} +1 -1
- package/dist/{registry-Ih5n4PVZ.cjs → registry-Cymq7Ah0.cjs} +97 -92
- package/dist/registry-Cymq7Ah0.cjs.map +1 -0
- package/dist/{registry-B23o9UWh.js → registry-tkacvJUI.js} +79 -91
- package/dist/registry-tkacvJUI.js.map +1 -0
- package/dist/{schemas-yId-bJhD.js → schemas-DM8sN_f0.js} +5 -7
- package/dist/{schemas-yId-bJhD.js.map → schemas-DM8sN_f0.js.map} +1 -1
- package/dist/{schemas-Q2dyOgc2.cjs → schemas-wDzbKdKa.cjs} +5 -7
- package/dist/{schemas-Q2dyOgc2.cjs.map → schemas-wDzbKdKa.cjs.map} +1 -1
- package/dist/schemas.cjs +3 -3
- package/dist/schemas.d.cts +1 -1
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.js +3 -3
- package/dist/{scoring-CaPS6q8b.cjs → scoring-D9tFvPEG.cjs} +22 -42
- package/dist/{scoring-CaPS6q8b.cjs.map → scoring-D9tFvPEG.cjs.map} +1 -1
- package/dist/{scoring-CLMdk8i9.js → scoring-DIBmo_cy.js} +22 -42
- package/dist/{scoring-CLMdk8i9.js.map → scoring-DIBmo_cy.js.map} +1 -1
- package/dist/scoring.cjs +2 -2
- package/dist/scoring.d.cts +2 -2
- package/dist/scoring.d.ts +2 -2
- package/dist/scoring.js +2 -2
- package/dist/{xapi-BX0hvRRB.cjs → xapi-Dyqcl3JK.cjs} +5 -8
- package/dist/{xapi-BX0hvRRB.cjs.map → xapi-Dyqcl3JK.cjs.map} +1 -1
- package/dist/{xapi-Cdk9fTvV.js → xapi-gCAo549Q.js} +5 -8
- package/dist/{xapi-Cdk9fTvV.js.map → xapi-gCAo549Q.js.map} +1 -1
- package/dist/xapi.cjs +1 -1
- package/dist/xapi.d.cts +1 -1
- package/dist/xapi.d.ts +1 -1
- package/dist/xapi.js +1 -1
- package/package.json +2 -2
- package/vectors/README.md +23 -0
- package/vectors/variants.d.mts +20 -0
- package/vectors/variants.json +5753 -0
- package/vectors/variants.mjs +67 -0
- package/dist/ai-i3jwXnpX.d.cts.map +0 -1
- package/dist/ai-i3jwXnpX.d.ts.map +0 -1
- package/dist/ai-writing-C4YRVrFi.cjs.map +0 -1
- package/dist/ai-writing-OJ5m_1EB.js.map +0 -1
- package/dist/index--U7hHV0s.d.cts.map +0 -1
- package/dist/index-CFRgZLhH.d.cts.map +0 -1
- package/dist/index-DeD8EI1D.d.ts.map +0 -1
- package/dist/index-Dj92T76o.d.ts.map +0 -1
- package/dist/index-Uh1u57yq.d.cts.map +0 -1
- package/dist/index-WBHSrIUU.d.ts.map +0 -1
- package/dist/registry-B23o9UWh.js.map +0 -1
- package/dist/registry-Ih5n4PVZ.cjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// \0rolldown/runtime.js
|
|
2
2
|
var __create = Object.create;
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -19,11 +19,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
19
19
|
value: mod,
|
|
20
20
|
enumerable: true
|
|
21
21
|
}) : target, mod));
|
|
22
|
-
//#endregion
|
|
23
22
|
let zod_v4 = require("zod/v4");
|
|
24
23
|
zod_v4 = __toESM(zod_v4, 1);
|
|
25
24
|
let zod_v4_core = require("zod/v4/core");
|
|
26
|
-
|
|
25
|
+
// src/schemas/ai.ts
|
|
27
26
|
/**
|
|
28
27
|
* What an author allows AI to do for one item: see `ActivityAiPermissions`.
|
|
29
28
|
* Loose like every content schema, so a key a later release adds survives an
|
|
@@ -33,8 +32,7 @@ const AiPermissionsSchema = zod_v4.looseObject({
|
|
|
33
32
|
explanations: zod_v4.boolean().optional(),
|
|
34
33
|
hints: zod_v4.boolean().optional()
|
|
35
34
|
});
|
|
36
|
-
|
|
37
|
-
//#region src/schemas/feedback.ts
|
|
35
|
+
// src/schemas/feedback.ts
|
|
38
36
|
/**
|
|
39
37
|
* Optional authored "overall feedback" shown after submission, selected by
|
|
40
38
|
* whether the learner passed (h5p-style overall feedback). Both fields are
|
|
@@ -44,8 +42,7 @@ const FeedbackSchema = zod_v4.looseObject({
|
|
|
44
42
|
correct: zod_v4.string().min(1).optional(),
|
|
45
43
|
incorrect: zod_v4.string().min(1).optional()
|
|
46
44
|
});
|
|
47
|
-
|
|
48
|
-
//#region src/schemas/text-length.ts
|
|
45
|
+
// src/schemas/text-length.ts
|
|
49
46
|
/**
|
|
50
47
|
* `schema`, refusing a string longer than `max` UTF-16 code units — its
|
|
51
48
|
* JavaScript `length`, the unit these limits have always counted in.
|
|
@@ -68,8 +65,7 @@ function maxUnits(schema, max) {
|
|
|
68
65
|
});
|
|
69
66
|
}).meta({ maxLength: max });
|
|
70
67
|
}
|
|
71
|
-
|
|
72
|
-
//#region src/schemas/media.ts
|
|
68
|
+
// src/schemas/media.ts
|
|
73
69
|
/**
|
|
74
70
|
* Optional media attached to an activity, rendered above the question or
|
|
75
71
|
* passage — e.g. a recording to listen to, or an embedded video to watch
|
|
@@ -267,8 +263,7 @@ const RedactedMediaSchema = zod_v4.strictObject({
|
|
|
267
263
|
error: "embed media requires an absolute http(s) provider URL. data:, blob:, and relative URLs are not allowed for embeds — the embed iframe runs with allow-scripts, and a data:/same-origin document there is an XSS vector.",
|
|
268
264
|
path: ["url"]
|
|
269
265
|
}).refine(posterFits, POSTER_FITS).refine(tracksFit, TRACKS_FIT).refine(tracksAreDistinct, TRACKS_DISTINCT);
|
|
270
|
-
|
|
271
|
-
//#region src/schemas/fill-in-the-blanks.ts
|
|
266
|
+
// src/schemas/fill-in-the-blanks.ts
|
|
272
267
|
/**
|
|
273
268
|
* Matches `{{ blank_id }}` placeholders in a passage, capturing the trimmed id.
|
|
274
269
|
* Exported for the draft checks in `authoring/`, which must read a passage
|
|
@@ -276,6 +271,12 @@ const RedactedMediaSchema = zod_v4.strictObject({
|
|
|
276
271
|
*/
|
|
277
272
|
const PLACEHOLDER_RE = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
278
273
|
/**
|
|
274
|
+
* The instructions of an item with a passage: plain text, with no `{{id}}`
|
|
275
|
+
* placeholder. Blanks and gaps live in the passage only, and one written here
|
|
276
|
+
* would be shown to the learner as it stands. Shared by Gap Select.
|
|
277
|
+
*/
|
|
278
|
+
const PassageInstructionsSchema = zod_v4.string().refine((text) => text.match(PLACEHOLDER_RE) === null, { error: "The instructions are plain text: a {{id}} placeholder belongs in the passage, where its blank or gap is." });
|
|
279
|
+
/**
|
|
279
280
|
* Zod schema for a `TextMatchPolicy` — the opt-in matching tolerances a blank
|
|
280
281
|
* may declare. Every default reproduces the v1 trim + case-fold semantics.
|
|
281
282
|
*/
|
|
@@ -323,6 +324,7 @@ const FillInTheBlanksDataSchema = zod_v4.looseObject({
|
|
|
323
324
|
type: zod_v4.literal("fill-in-the-blanks"),
|
|
324
325
|
id: zod_v4.string().min(1),
|
|
325
326
|
title: zod_v4.string().min(1),
|
|
327
|
+
instructions: PassageInstructionsSchema.optional(),
|
|
326
328
|
passage: zod_v4.string().min(1),
|
|
327
329
|
passageHtml: zod_v4.string().optional(),
|
|
328
330
|
blanks: zod_v4.array(BlankConfigSchema).min(1),
|
|
@@ -354,8 +356,7 @@ const FillInTheBlanksDataSchema = zod_v4.looseObject({
|
|
|
354
356
|
error: "Each blank id must appear exactly once in blanks[] and have exactly one matching {{id}} placeholder in the passage, and vice versa.",
|
|
355
357
|
path: ["passage"]
|
|
356
358
|
});
|
|
357
|
-
|
|
358
|
-
//#region src/answer-leak.ts
|
|
359
|
+
// src/answer-leak.ts
|
|
359
360
|
/**
|
|
360
361
|
* Whether a text gives an answer away: the rule an AI hint is held to, and the
|
|
361
362
|
* one the item critic holds an author's own hint, title and passage to.
|
|
@@ -442,8 +443,7 @@ function revealsAnswer(text, answer, passage, position) {
|
|
|
442
443
|
if (before === void 0 && after === void 0) return containsWords(words, needle);
|
|
443
444
|
return before !== void 0 && containsWords(words, [before, ...needle]) || after !== void 0 && containsWords(words, [...needle, after]);
|
|
444
445
|
}
|
|
445
|
-
|
|
446
|
-
//#region src/built-in-types.ts
|
|
446
|
+
// src/built-in-types.ts
|
|
447
447
|
/**
|
|
448
448
|
* The activity types the SDK ships, in one closed list.
|
|
449
449
|
*
|
|
@@ -479,8 +479,7 @@ function isBuiltInActivityType(type) {
|
|
|
479
479
|
* @internal
|
|
480
480
|
*/
|
|
481
481
|
function everyBuiltInTypeHandled(_value) {}
|
|
482
|
-
|
|
483
|
-
//#region src/scoring/dictation/edit-distance.ts
|
|
482
|
+
// src/scoring/dictation/edit-distance.ts
|
|
484
483
|
/**
|
|
485
484
|
* The code points of `text`, as numbers. A surrogate pair is one code point; a
|
|
486
485
|
* lone surrogate iterates as one code point too — deterministic, never thrown.
|
|
@@ -532,8 +531,7 @@ function similarity(a, b) {
|
|
|
532
531
|
const max = Math.max(codePoints(a).length, codePoints(b).length);
|
|
533
532
|
return max === 0 ? 0 : (max - editDistance(a, b)) / max;
|
|
534
533
|
}
|
|
535
|
-
|
|
536
|
-
//#region src/validation-scope.ts
|
|
534
|
+
// src/validation-scope.ts
|
|
537
535
|
/**
|
|
538
536
|
* Work shared for the length of one outermost validation call.
|
|
539
537
|
*
|
|
@@ -572,8 +570,7 @@ function scopeCache(key, create) {
|
|
|
572
570
|
}
|
|
573
571
|
return value;
|
|
574
572
|
}
|
|
575
|
-
|
|
576
|
-
//#region src/scoring/dictation/unicode-joining.ts
|
|
573
|
+
// src/scoring/dictation/unicode-joining.ts
|
|
577
574
|
/**
|
|
578
575
|
* Unicode data the dictation normaliser reads when it decides whether a joiner
|
|
579
576
|
* changes how the text is drawn (see `normalize.ts`): the viramas, and which
|
|
@@ -791,8 +788,7 @@ const JOINS_BACKWARD = [
|
|
|
791
788
|
[69577, 69578],
|
|
792
789
|
[125184, 125251]
|
|
793
790
|
];
|
|
794
|
-
|
|
795
|
-
//#region src/scoring/dictation/normalize.ts
|
|
791
|
+
// src/scoring/dictation/normalize.ts
|
|
796
792
|
/**
|
|
797
793
|
* The longest transcript a dictation accepts, in code points, before and after
|
|
798
794
|
* its equivalences are applied — and its rules may not grow it past twice
|
|
@@ -1752,8 +1748,7 @@ function searchReveal(forms, candidate) {
|
|
|
1752
1748
|
return fields.some((field) => containsPhrase(field, phrase));
|
|
1753
1749
|
});
|
|
1754
1750
|
}
|
|
1755
|
-
|
|
1756
|
-
//#region src/scoring/dictation/align.ts
|
|
1751
|
+
// src/scoring/dictation/align.ts
|
|
1757
1752
|
/**
|
|
1758
1753
|
* The words the scorer can emit a detail for, one list per candidate — index 0
|
|
1759
1754
|
* is the transcript, index n is `acceptedTranscripts[n − 1]` — each word in the
|
|
@@ -1952,8 +1947,7 @@ function alignWords(reference, attempt) {
|
|
|
1952
1947
|
}
|
|
1953
1948
|
return words;
|
|
1954
1949
|
}
|
|
1955
|
-
|
|
1956
|
-
//#region src/errors.ts
|
|
1950
|
+
// src/errors.ts
|
|
1957
1951
|
/** Thrown when activity data fails schema validation at a component boundary. */
|
|
1958
1952
|
var ActivitySchemaError = class extends Error {
|
|
1959
1953
|
activityType;
|
|
@@ -2007,8 +2001,7 @@ var DeferredScoringError = class extends Error {
|
|
|
2007
2001
|
this.name = "DeferredScoringError";
|
|
2008
2002
|
}
|
|
2009
2003
|
};
|
|
2010
|
-
|
|
2011
|
-
//#region src/schemas/after-issues.ts
|
|
2004
|
+
// src/schemas/after-issues.ts
|
|
2012
2005
|
/**
|
|
2013
2006
|
* A check zod runs even when another field was refused. An ordinary check is
|
|
2014
2007
|
* skipped once any issue has been reported, so an author fixing a recording's
|
|
@@ -2045,8 +2038,7 @@ function parsedFields(payload) {
|
|
|
2045
2038
|
refused
|
|
2046
2039
|
};
|
|
2047
2040
|
}
|
|
2048
|
-
|
|
2049
|
-
//#region src/schemas/dictation.ts
|
|
2041
|
+
// src/schemas/dictation.ts
|
|
2050
2042
|
/**
|
|
2051
2043
|
* Zod schema for the slower second recording of a dictation. Loose like every
|
|
2052
2044
|
* content schema (a sidecar survives), audio only, and — deliberately — with no
|
|
@@ -2228,8 +2220,7 @@ function groupCaptionsField(group, written) {
|
|
|
2228
2220
|
}
|
|
2229
2221
|
/** The message every validator gives for {@link groupCaptionsRevealDictation}. */
|
|
2230
2222
|
const GROUP_CAPTIONS_REVEAL_DICTATION = "The stimulus recording carries captions, and a dictation in this group plays that recording: the captions are the answer. Remove the captions, or give the dictation its own recording.";
|
|
2231
|
-
|
|
2232
|
-
//#region src/authoring/issues.ts
|
|
2223
|
+
// src/authoring/issues.ts
|
|
2233
2224
|
/**
|
|
2234
2225
|
* Every issue code the SDK's draft checks can report, with its severity.
|
|
2235
2226
|
*
|
|
@@ -2565,8 +2556,7 @@ function coveredPathsOf(reported) {
|
|
|
2565
2556
|
}
|
|
2566
2557
|
return covered;
|
|
2567
2558
|
}
|
|
2568
|
-
|
|
2569
|
-
//#region src/authoring/dictation.ts
|
|
2559
|
+
// src/authoring/dictation.ts
|
|
2570
2560
|
/**
|
|
2571
2561
|
* Draft support for `dictation`.
|
|
2572
2562
|
*
|
|
@@ -2756,8 +2746,7 @@ function checkTolerance(tolerance) {
|
|
|
2756
2746
|
}
|
|
2757
2747
|
return issues;
|
|
2758
2748
|
}
|
|
2759
|
-
|
|
2760
|
-
//#region src/count-words.ts
|
|
2749
|
+
// src/count-words.ts
|
|
2761
2750
|
/**
|
|
2762
2751
|
* Canonical word counter for written-response bounds: tokens are
|
|
2763
2752
|
* maximal runs of non-whitespace (split on `\s+`), so hyphenated forms
|
|
@@ -2862,8 +2851,7 @@ function levelDistribution(values, count, chosen) {
|
|
|
2862
2851
|
const sum = read.reduce((total, p) => total + p, 0);
|
|
2863
2852
|
return Math.abs(sum - 1) <= 1e-6 && read[chosen] === Math.max(...read) ? read : null;
|
|
2864
2853
|
}
|
|
2865
|
-
|
|
2866
|
-
//#region src/scoring/strategies/all-or-nothing.ts
|
|
2854
|
+
// src/scoring/strategies/all-or-nothing.ts
|
|
2867
2855
|
/**
|
|
2868
2856
|
* All-or-nothing scoring: full credit only when every item is correct.
|
|
2869
2857
|
*
|
|
@@ -2873,8 +2861,7 @@ function levelDistribution(values, count, chosen) {
|
|
|
2873
2861
|
function allOrNothingStrategy(correctItems) {
|
|
2874
2862
|
return correctItems.every((isCorrect) => isCorrect) ? 1 : 0;
|
|
2875
2863
|
}
|
|
2876
|
-
|
|
2877
|
-
//#region src/scoring/strategies/partial.ts
|
|
2864
|
+
// src/scoring/strategies/partial.ts
|
|
2878
2865
|
/**
|
|
2879
2866
|
* Partial-credit scoring for Multiple Choice — balanced/symmetric scheme.
|
|
2880
2867
|
*
|
|
@@ -2914,8 +2901,7 @@ function partialStrategy(correctSelected, incorrectSelected, totalCorrect, total
|
|
|
2914
2901
|
function partialBlankStrategy(correctBlanks, totalBlanks) {
|
|
2915
2902
|
return correctBlanks / totalBlanks;
|
|
2916
2903
|
}
|
|
2917
|
-
|
|
2918
|
-
//#region src/scoring/text-match.ts
|
|
2904
|
+
// src/scoring/text-match.ts
|
|
2919
2905
|
/** Combining marks (any script) removed for diacritic folding after NFD decomposition. */
|
|
2920
2906
|
const COMBINING_MARKS_RE = /\p{M}/gu;
|
|
2921
2907
|
/**
|
|
@@ -3008,8 +2994,7 @@ function matchText(input, accepted, policy = {}) {
|
|
|
3008
2994
|
via: "none"
|
|
3009
2995
|
};
|
|
3010
2996
|
}
|
|
3011
|
-
|
|
3012
|
-
//#region src/scoring/activity-scorers/fill-in-the-blanks.ts
|
|
2997
|
+
// src/scoring/activity-scorers/fill-in-the-blanks.ts
|
|
3013
2998
|
/**
|
|
3014
2999
|
* Resolves the effective match policy for a blank. The legacy
|
|
3015
3000
|
* `caseSensitive` / `trimWhitespace` flags map onto the baseline policy
|
|
@@ -3053,8 +3038,7 @@ function scoreFillInTheBlanks(data, response) {
|
|
|
3053
3038
|
details
|
|
3054
3039
|
};
|
|
3055
3040
|
}
|
|
3056
|
-
|
|
3057
|
-
//#region src/authoring/findings.ts
|
|
3041
|
+
// src/authoring/findings.ts
|
|
3058
3042
|
/**
|
|
3059
3043
|
* Every finding code the SDK's item critic can report, with its severity.
|
|
3060
3044
|
*
|
|
@@ -3073,6 +3057,7 @@ const ITEM_FINDING_SEVERITY = {
|
|
|
3073
3057
|
fib_hint_reveals_answer: "warning",
|
|
3074
3058
|
fib_answer_in_passage: "warning",
|
|
3075
3059
|
fib_accepted_answer_redundant: "advice",
|
|
3060
|
+
fib_tolerance_spans_words: "advice",
|
|
3076
3061
|
gs_title_reveals_answer: "warning",
|
|
3077
3062
|
gs_choices_duplicate: "warning",
|
|
3078
3063
|
gs_bank_no_distractor: "warning",
|
|
@@ -3083,7 +3068,12 @@ const ITEM_FINDING_SEVERITY = {
|
|
|
3083
3068
|
media_transcript_unused: "advice",
|
|
3084
3069
|
media_script_differs: "warning",
|
|
3085
3070
|
media_transcript_differs: "warning",
|
|
3086
|
-
set_key_position_same: "warning"
|
|
3071
|
+
set_key_position_same: "warning",
|
|
3072
|
+
set_key_position_bias: "warning",
|
|
3073
|
+
set_key_longest_bias: "warning",
|
|
3074
|
+
set_stem_duplicate: "warning",
|
|
3075
|
+
set_item_answers_item: "warning",
|
|
3076
|
+
set_key_repeated: "advice"
|
|
3087
3077
|
};
|
|
3088
3078
|
function finding(code, path, message) {
|
|
3089
3079
|
return {
|
|
@@ -3107,8 +3097,7 @@ function normaliseFinding(found) {
|
|
|
3107
3097
|
severity: documented ?? (found.severity === "advice" ? "advice" : "warning")
|
|
3108
3098
|
};
|
|
3109
3099
|
}
|
|
3110
|
-
|
|
3111
|
-
//#region src/authoring/critique.ts
|
|
3100
|
+
// src/authoring/critique.ts
|
|
3112
3101
|
/**
|
|
3113
3102
|
* The built-in item critic: what an experienced item writer points out on
|
|
3114
3103
|
* review, as far as a rule can see it without a model.
|
|
@@ -3274,6 +3263,17 @@ function critiqueFillInTheBlanks(draft) {
|
|
|
3274
3263
|
laterIndex
|
|
3275
3264
|
], `"${laterText}" is already accepted as "${accepted[earlier]}" under this blank's matching.`));
|
|
3276
3265
|
});
|
|
3266
|
+
const forgiven = policyFor(blank).levenshtein ?? 0;
|
|
3267
|
+
const spanning = accepted.findIndex((answer) => {
|
|
3268
|
+
const text = written(answer);
|
|
3269
|
+
return text !== void 0 && /\s/.test(text.trim());
|
|
3270
|
+
});
|
|
3271
|
+
if (forgiven > 0 && spanning !== -1) findings.push(finding("fib_tolerance_spans_words", [
|
|
3272
|
+
"blanks",
|
|
3273
|
+
index,
|
|
3274
|
+
"acceptedAnswers",
|
|
3275
|
+
spanning
|
|
3276
|
+
], `Blank ${ordinal(index)} forgives ${forgiven === 1 ? "one edit" : `${forgiven} edits`} over an answer of several words, so "${accepted[spanning]}" with one word in another form is marked right. Make it a one-word blank, or take the tolerance off.`));
|
|
3277
3277
|
});
|
|
3278
3278
|
return findings;
|
|
3279
3279
|
}
|
|
@@ -3391,8 +3391,7 @@ function keyPositionFinding(items, path) {
|
|
|
3391
3391
|
if (positions.length < KEY_POSITION_MINIMUM || !positions.every((at) => at === positions[0])) return [];
|
|
3392
3392
|
return [finding("set_key_position_same", path, `In all ${positions.length} single-answer questions the right option is option ${ordinal(positions[0])}. Vary its position, or shuffle the options.`)];
|
|
3393
3393
|
}
|
|
3394
|
-
|
|
3395
|
-
//#region src/authoring/fill-in-the-blanks.ts
|
|
3394
|
+
// src/authoring/fill-in-the-blanks.ts
|
|
3396
3395
|
/**
|
|
3397
3396
|
* Draft support for `fill-in-the-blanks`.
|
|
3398
3397
|
*
|
|
@@ -3524,8 +3523,7 @@ function pairsOneToOne$1(placeholders, blanks) {
|
|
|
3524
3523
|
if (placeholders.size !== blankIds.length) return false;
|
|
3525
3524
|
return blankIds.every((id) => typeof id === "string" && placeholders.get(id) === 1);
|
|
3526
3525
|
}
|
|
3527
|
-
|
|
3528
|
-
//#region src/authoring/gap-select.ts
|
|
3526
|
+
// src/authoring/gap-select.ts
|
|
3529
3527
|
/** Mirrors `GapSelectChoiceSchema` arrays: `.min(2)` on both a gap's own list and a bank. */
|
|
3530
3528
|
const MIN_CHOICES = 2;
|
|
3531
3529
|
/**
|
|
@@ -3723,8 +3721,7 @@ function pairsOneToOne(placeholders, gaps) {
|
|
|
3723
3721
|
if (new Set(ids).size !== ids.length || placeholders.size !== ids.length) return false;
|
|
3724
3722
|
return ids.every((id) => typeof id === "string" && placeholders.get(id) === 1);
|
|
3725
3723
|
}
|
|
3726
|
-
|
|
3727
|
-
//#region src/schemas/multiple-choice.ts
|
|
3724
|
+
// src/schemas/multiple-choice.ts
|
|
3728
3725
|
/**
|
|
3729
3726
|
* Zod schema for a single Multiple Choice option. Loose: unknown keys are
|
|
3730
3727
|
* preserved through validation (forward-compat / consumer sidecars — B7).
|
|
@@ -3788,6 +3785,7 @@ const MultipleChoiceDataSchema = zod_v4.looseObject({
|
|
|
3788
3785
|
type: zod_v4.literal("multiple-choice"),
|
|
3789
3786
|
id: zod_v4.string().min(1),
|
|
3790
3787
|
title: zod_v4.string().min(1),
|
|
3788
|
+
instructions: zod_v4.string().optional(),
|
|
3791
3789
|
question: zod_v4.string().min(1),
|
|
3792
3790
|
questionHtml: zod_v4.string().optional(),
|
|
3793
3791
|
mode: zod_v4.enum(["single", "multi"]),
|
|
@@ -3817,8 +3815,7 @@ const MultipleChoiceDataSchema = zod_v4.looseObject({
|
|
|
3817
3815
|
error: "Option ids must be unique within the activity.",
|
|
3818
3816
|
path: ["options"]
|
|
3819
3817
|
});
|
|
3820
|
-
|
|
3821
|
-
//#region src/authoring/multiple-choice.ts
|
|
3818
|
+
// src/authoring/multiple-choice.ts
|
|
3822
3819
|
/** Mirrors `MultipleChoiceDataSchema`: `options` is `.min(2).max(26)`. */
|
|
3823
3820
|
const MIN_OPTIONS = 2;
|
|
3824
3821
|
const MAX_OPTIONS = 26;
|
|
@@ -3921,8 +3918,7 @@ function checkOptionMedia(media, index, ordinal) {
|
|
|
3921
3918
|
if (kind === "video" || kind === "embed") return [issue("mc_option_media_kind", [...path, "type"], `Option ${ordinal} carries ${kind === "embed" ? "an embedded player" : "a video"}, which cannot be an option: its controls swallow the click that selects the answer. Use a picture or a recording.`)];
|
|
3922
3919
|
return checkMedia(media, path, MultipleChoiceOptionMediaSchema);
|
|
3923
3920
|
}
|
|
3924
|
-
|
|
3925
|
-
//#region src/scoring/speech/limits.ts
|
|
3921
|
+
// src/scoring/speech/limits.ts
|
|
3926
3922
|
/**
|
|
3927
3923
|
* The longest reference text a read-aloud item accepts, in code points, before
|
|
3928
3924
|
* and after normalisation. It is the dictation transcript cap on purpose: the
|
|
@@ -3972,8 +3968,7 @@ const SPEECH_ASSESSMENT_MAX_WORDS = 1e3;
|
|
|
3972
3968
|
* read-aloud item comes near it.
|
|
3973
3969
|
*/
|
|
3974
3970
|
const SPEECH_ASSESSMENT_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH;
|
|
3975
|
-
|
|
3976
|
-
//#region src/scoring/speech/locale.ts
|
|
3971
|
+
// src/scoring/speech/locale.ts
|
|
3977
3972
|
/**
|
|
3978
3973
|
* A BCP 47 tag in the one spelling read-aloud accepts: a lowercase language of
|
|
3979
3974
|
* two or three letters, an optional title-case script, and a region of two
|
|
@@ -3989,8 +3984,7 @@ const SPEECH_ASSESSMENT_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH;
|
|
|
3989
3984
|
* Internal: the content schema and the assessment validator share it.
|
|
3990
3985
|
*/
|
|
3991
3986
|
const CANONICAL_LOCALE_RE = /^[a-z]{2,3}(?:-[A-Z][a-z]{3})?-(?:[A-Z]{2}|[0-9]{3})$/;
|
|
3992
|
-
|
|
3993
|
-
//#region src/schemas/read-aloud.ts
|
|
3987
|
+
// src/schemas/read-aloud.ts
|
|
3994
3988
|
/** The dimensions a read-aloud grade can be made of, in the order they are documented. */
|
|
3995
3989
|
const READ_ALOUD_DIMENSIONS = [
|
|
3996
3990
|
"accuracy",
|
|
@@ -4143,8 +4137,7 @@ const ReadAloudDataSchema = zod_v4.looseObject({
|
|
|
4143
4137
|
if (minSeconds !== void 0 && minSeconds >= maxSeconds) report(["recording", "minSeconds"], minSeconds, "The shortest take must be shorter than the longest.");
|
|
4144
4138
|
}
|
|
4145
4139
|
}));
|
|
4146
|
-
|
|
4147
|
-
//#region src/authoring/read-aloud.ts
|
|
4140
|
+
// src/authoring/read-aloud.ts
|
|
4148
4141
|
/**
|
|
4149
4142
|
* Draft support for `read-aloud`.
|
|
4150
4143
|
*
|
|
@@ -4307,8 +4300,7 @@ function checkSlowRecording(draft) {
|
|
|
4307
4300
|
if (typeof slow.url === "string" && slow.url !== "" && slow.url === media.url) issues.push(issue("ra_slow_media_same_recording", ["slowMedia", "url"], "The slow model recording is the same file as the recording. Point it at the slower reading."));
|
|
4308
4301
|
return issues;
|
|
4309
4302
|
}
|
|
4310
|
-
|
|
4311
|
-
//#region src/authoring/written-response.ts
|
|
4303
|
+
// src/authoring/written-response.ts
|
|
4312
4304
|
/**
|
|
4313
4305
|
* Draft support for `written-response`.
|
|
4314
4306
|
*
|
|
@@ -4396,8 +4388,7 @@ function checkCriteria(criteria) {
|
|
|
4396
4388
|
else if (totalWeight === Number.POSITIVE_INFINITY) issues.push(issue("wr_rubric_weights_too_large", ["rubric", "criteria"], "The rubric weights add up to more than can be calculated with. Use smaller weights."));
|
|
4397
4389
|
return issues;
|
|
4398
4390
|
}
|
|
4399
|
-
|
|
4400
|
-
//#region src/schemas/gap-select.ts
|
|
4391
|
+
// src/schemas/gap-select.ts
|
|
4401
4392
|
/**
|
|
4402
4393
|
* Zod schema for one selectable choice. Loose, like every other schema here:
|
|
4403
4394
|
* unknown keys are preserved so a consumer sidecar survives validation.
|
|
@@ -4461,6 +4452,7 @@ const GapSelectDataSchema = zod_v4.looseObject({
|
|
|
4461
4452
|
type: zod_v4.literal("gap-select"),
|
|
4462
4453
|
id: zod_v4.string().min(1),
|
|
4463
4454
|
title: zod_v4.string().min(1),
|
|
4455
|
+
instructions: PassageInstructionsSchema.optional(),
|
|
4464
4456
|
passage: zod_v4.string().min(1),
|
|
4465
4457
|
passageHtml: zod_v4.string().optional(),
|
|
4466
4458
|
gaps: zod_v4.array(GapSelectGapSchema).min(1),
|
|
@@ -4521,8 +4513,7 @@ const GapSelectDataSchema = zod_v4.looseObject({
|
|
|
4521
4513
|
error: "Each gap needs unique choice ids and a `correctChoiceId` that is one of the choices it offers.",
|
|
4522
4514
|
path: ["gaps"]
|
|
4523
4515
|
});
|
|
4524
|
-
|
|
4525
|
-
//#region src/schemas/written-response.ts
|
|
4516
|
+
// src/schemas/written-response.ts
|
|
4526
4517
|
/** Zod schema for a single rubric criterion. Loose: unknown keys preserved. */
|
|
4527
4518
|
const WrittenResponseRubricCriterionSchema = zod_v4.looseObject({
|
|
4528
4519
|
name: zod_v4.string().min(1),
|
|
@@ -4593,8 +4584,7 @@ const WrittenResponseDataSchema = zod_v4.looseObject({
|
|
|
4593
4584
|
error: "maxWords must be greater than or equal to minWords.",
|
|
4594
4585
|
path: ["maxWords"]
|
|
4595
4586
|
});
|
|
4596
|
-
|
|
4597
|
-
//#region src/schemas/redacted.ts
|
|
4587
|
+
// src/schemas/redacted.ts
|
|
4598
4588
|
/**
|
|
4599
4589
|
* Schemas for REDACTED activity data — the learner-safe projection `redact()`
|
|
4600
4590
|
* produces (R7). Deliberately STRICT (`z.strictObject`), the opposite of the
|
|
@@ -4658,6 +4648,7 @@ const RedactedMultipleChoiceOptionSchema = zod_v4.strictObject({
|
|
|
4658
4648
|
const RedactedMultipleChoiceDataSchema = zod_v4.strictObject({
|
|
4659
4649
|
...redactedBase,
|
|
4660
4650
|
type: zod_v4.literal("multiple-choice"),
|
|
4651
|
+
instructions: zod_v4.string().optional(),
|
|
4661
4652
|
question: zod_v4.string().min(1),
|
|
4662
4653
|
questionHtml: zod_v4.string().optional(),
|
|
4663
4654
|
mode: zod_v4.enum(["single", "multi"]),
|
|
@@ -4673,6 +4664,7 @@ const RedactedBlankConfigSchema = zod_v4.strictObject({
|
|
|
4673
4664
|
const RedactedFillInTheBlanksDataSchema = zod_v4.strictObject({
|
|
4674
4665
|
...redactedBase,
|
|
4675
4666
|
type: zod_v4.literal("fill-in-the-blanks"),
|
|
4667
|
+
instructions: zod_v4.string().optional(),
|
|
4676
4668
|
passage: zod_v4.string().min(1),
|
|
4677
4669
|
passageHtml: zod_v4.string().optional(),
|
|
4678
4670
|
blanks: zod_v4.array(RedactedBlankConfigSchema).min(1)
|
|
@@ -4711,6 +4703,7 @@ const RedactedGapSelectGapSchema = zod_v4.strictObject({
|
|
|
4711
4703
|
const RedactedGapSelectDataSchema = zod_v4.strictObject({
|
|
4712
4704
|
...redactedBase,
|
|
4713
4705
|
type: zod_v4.literal("gap-select"),
|
|
4706
|
+
instructions: zod_v4.string().optional(),
|
|
4714
4707
|
passage: zod_v4.string().min(1),
|
|
4715
4708
|
passageHtml: zod_v4.string().optional(),
|
|
4716
4709
|
gaps: zod_v4.array(RedactedGapSelectGapSchema).min(1),
|
|
@@ -4836,8 +4829,7 @@ const RedactedReadAloudDataSchema = zod_v4.strictObject({
|
|
|
4836
4829
|
path: ["slowMedia", "url"]
|
|
4837
4830
|
});
|
|
4838
4831
|
});
|
|
4839
|
-
|
|
4840
|
-
//#region src/scoring/activity-scorers/dictation.ts
|
|
4832
|
+
// src/scoring/activity-scorers/dictation.ts
|
|
4841
4833
|
/**
|
|
4842
4834
|
* Scores a Dictation response: the character-level similarity of what the
|
|
4843
4835
|
* learner typed to the transcript, over the whole sentence.
|
|
@@ -4876,8 +4868,7 @@ function scoreDictation(data, response) {
|
|
|
4876
4868
|
details
|
|
4877
4869
|
};
|
|
4878
4870
|
}
|
|
4879
|
-
|
|
4880
|
-
//#region src/scoring/activity-scorers/gap-select.ts
|
|
4871
|
+
// src/scoring/activity-scorers/gap-select.ts
|
|
4881
4872
|
/**
|
|
4882
4873
|
* The choices a gap offers: its own list, or the bank it names.
|
|
4883
4874
|
*
|
|
@@ -4931,8 +4922,7 @@ function scoreGapSelect(data, response) {
|
|
|
4931
4922
|
details
|
|
4932
4923
|
};
|
|
4933
4924
|
}
|
|
4934
|
-
|
|
4935
|
-
//#region src/scoring/activity-scorers/multiple-choice.ts
|
|
4925
|
+
// src/scoring/activity-scorers/multiple-choice.ts
|
|
4936
4926
|
/**
|
|
4937
4927
|
* Scores a Multiple Choice response. Pure; trusts its typed inputs (validation
|
|
4938
4928
|
* is the component boundary's job). Options are looked up by id; an unknown
|
|
@@ -4976,8 +4966,7 @@ function scoreMultipleChoice(data, response) {
|
|
|
4976
4966
|
details
|
|
4977
4967
|
};
|
|
4978
4968
|
}
|
|
4979
|
-
|
|
4980
|
-
//#region src/registry/define.ts
|
|
4969
|
+
// src/registry/define.ts
|
|
4981
4970
|
/**
|
|
4982
4971
|
* Identity helper that gives full type inference when authoring a descriptor:
|
|
4983
4972
|
*
|
|
@@ -4992,8 +4981,7 @@ function scoreMultipleChoice(data, response) {
|
|
|
4992
4981
|
function defineActivityType(descriptor) {
|
|
4993
4982
|
return descriptor;
|
|
4994
4983
|
}
|
|
4995
|
-
|
|
4996
|
-
//#region src/registry/keep-when.ts
|
|
4984
|
+
// src/registry/keep-when.ts
|
|
4997
4985
|
/**
|
|
4998
4986
|
* A nested field policy that keeps its field only when the field's value
|
|
4999
4987
|
* passes a test. Internal: the symbol is never exported, so no host policy can
|
|
@@ -5018,8 +5006,7 @@ function keepWhen(policy, test) {
|
|
|
5018
5006
|
function guardOf(policy) {
|
|
5019
5007
|
return policy[KEEP_WHEN];
|
|
5020
5008
|
}
|
|
5021
|
-
|
|
5022
|
-
//#region src/registry/builtins.ts
|
|
5009
|
+
// src/registry/builtins.ts
|
|
5023
5010
|
/**
|
|
5024
5011
|
* Where the built-in types keep their files (`mediaSlots`). Every type has its
|
|
5025
5012
|
* `media`; dictation and read-aloud add a slower recording; a multiple-choice
|
|
@@ -5137,6 +5124,7 @@ const TEXT_MATCH_FIELD_POLICY = {
|
|
|
5137
5124
|
};
|
|
5138
5125
|
const MULTIPLE_CHOICE_FIELD_POLICY = {
|
|
5139
5126
|
...SHARED_PUBLIC_FIELDS,
|
|
5127
|
+
instructions: "public",
|
|
5140
5128
|
question: "public",
|
|
5141
5129
|
questionHtml: "public",
|
|
5142
5130
|
mode: "public",
|
|
@@ -5171,6 +5159,7 @@ const MULTIPLE_CHOICE_FIELD_POLICY = {
|
|
|
5171
5159
|
*/
|
|
5172
5160
|
const GAP_SELECT_FIELD_POLICY = {
|
|
5173
5161
|
...SHARED_PUBLIC_FIELDS,
|
|
5162
|
+
instructions: "public",
|
|
5174
5163
|
passage: "public",
|
|
5175
5164
|
passageHtml: "public",
|
|
5176
5165
|
presentation: "public",
|
|
@@ -5197,6 +5186,7 @@ const GAP_SELECT_FIELD_POLICY = {
|
|
|
5197
5186
|
};
|
|
5198
5187
|
const FILL_IN_THE_BLANKS_FIELD_POLICY = {
|
|
5199
5188
|
...SHARED_PUBLIC_FIELDS,
|
|
5189
|
+
instructions: "public",
|
|
5200
5190
|
passage: "public",
|
|
5201
5191
|
passageHtml: "public",
|
|
5202
5192
|
scoringStrategy: "answer-key",
|
|
@@ -5499,8 +5489,7 @@ const BUILT_IN_DESCRIPTORS = {
|
|
|
5499
5489
|
dictation: dictationType,
|
|
5500
5490
|
"read-aloud": readAloudType
|
|
5501
5491
|
};
|
|
5502
|
-
|
|
5503
|
-
//#region src/schemas/read-schema.ts
|
|
5492
|
+
// src/schemas/read-schema.ts
|
|
5504
5493
|
/**
|
|
5505
5494
|
* How every entry point reads a schema — `validateActivity`, `validateDraft`,
|
|
5506
5495
|
* `validateItemGroup`, `redact`, `assertRedacted` — so a schema is read one way
|
|
@@ -5616,8 +5605,7 @@ function standardJsonSchemaOf(schema, target = "draft-07") {
|
|
|
5616
5605
|
const generated = converter.output({ target });
|
|
5617
5606
|
return generated !== null && typeof generated === "object" && !Array.isArray(generated) ? generated : void 0;
|
|
5618
5607
|
}
|
|
5619
|
-
|
|
5620
|
-
//#region src/registry/registry.ts
|
|
5608
|
+
// src/registry/registry.ts
|
|
5621
5609
|
/**
|
|
5622
5610
|
* Module-scoped default registry (deliberate — no registry instances until a
|
|
5623
5611
|
* second consumer exists), created holding the SDK's own types.
|
|
@@ -5663,7 +5651,6 @@ function getActivityTypeDescriptor(type) {
|
|
|
5663
5651
|
function registeredActivityTypes() {
|
|
5664
5652
|
return [...registry.keys()];
|
|
5665
5653
|
}
|
|
5666
|
-
//#endregion
|
|
5667
5654
|
Object.defineProperty(exports, "ActivitySchemaError", {
|
|
5668
5655
|
enumerable: true,
|
|
5669
5656
|
get: function() {
|
|
@@ -5778,6 +5765,12 @@ Object.defineProperty(exports, "MultipleChoiceOptionMediaSchema", {
|
|
|
5778
5765
|
return MultipleChoiceOptionMediaSchema;
|
|
5779
5766
|
}
|
|
5780
5767
|
});
|
|
5768
|
+
Object.defineProperty(exports, "PLACEHOLDER_RE", {
|
|
5769
|
+
enumerable: true,
|
|
5770
|
+
get: function() {
|
|
5771
|
+
return PLACEHOLDER_RE;
|
|
5772
|
+
}
|
|
5773
|
+
});
|
|
5781
5774
|
Object.defineProperty(exports, "READ_ALOUD_MAX_DIMENSION_WEIGHT", {
|
|
5782
5775
|
enumerable: true,
|
|
5783
5776
|
get: function() {
|
|
@@ -6084,6 +6077,12 @@ Object.defineProperty(exports, "numberedPassage", {
|
|
|
6084
6077
|
return numberedPassage;
|
|
6085
6078
|
}
|
|
6086
6079
|
});
|
|
6080
|
+
Object.defineProperty(exports, "passageWithoutPlaceholders", {
|
|
6081
|
+
enumerable: true,
|
|
6082
|
+
get: function() {
|
|
6083
|
+
return passageWithoutPlaceholders;
|
|
6084
|
+
}
|
|
6085
|
+
});
|
|
6087
6086
|
Object.defineProperty(exports, "pathKey", {
|
|
6088
6087
|
enumerable: true,
|
|
6089
6088
|
get: function() {
|
|
@@ -6096,6 +6095,12 @@ Object.defineProperty(exports, "placeholderOrder", {
|
|
|
6096
6095
|
return placeholderOrder;
|
|
6097
6096
|
}
|
|
6098
6097
|
});
|
|
6098
|
+
Object.defineProperty(exports, "policyFor", {
|
|
6099
|
+
enumerable: true,
|
|
6100
|
+
get: function() {
|
|
6101
|
+
return policyFor;
|
|
6102
|
+
}
|
|
6103
|
+
});
|
|
6099
6104
|
Object.defineProperty(exports, "readAloudType", {
|
|
6100
6105
|
enumerable: true,
|
|
6101
6106
|
get: function() {
|
|
@@ -6157,4 +6162,4 @@ Object.defineProperty(exports, "writtenResponseType", {
|
|
|
6157
6162
|
}
|
|
6158
6163
|
});
|
|
6159
6164
|
|
|
6160
|
-
//# sourceMappingURL=registry-
|
|
6165
|
+
//# sourceMappingURL=registry-Cymq7Ah0.cjs.map
|