@intellectif/lk-core 0.10.0 → 0.11.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 CHANGED
@@ -1,5 +1,35 @@
1
1
  # @intellectif/lk-core
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 722de91: Node 22 is the floor, and the published `engines` says so.
8
+
9
+ Both packages declared `engines: { node: '>=20' }` while CI stopped testing Node 20 in `e17f5fa` (pnpm 11 compatibility) and Node 20 itself reached end of life in April 2026. A support claim nothing verifies is worse than a narrow one: it invites an install onto a runtime no test has touched for months. The floor is now `>=22`, which is what CI has actually been proving all along — Node 22 (the LTS most consumers run) and Node 24 (the Node the Release job builds the published tarball on).
10
+
11
+ If you are still on Node 20, this is the release to stop at; nothing here changes behaviour on a supported runtime.
12
+
13
+ ## 0.10.1
14
+
15
+ ### Patch Changes
16
+
17
+ - ea2d620: `<GapSelect>` — the renderer the dropdown cloze shipped without.
18
+
19
+ `lk-core@0.10.0` registered `gap-select` and `lk-react` had no branch for it. An authored item validated, scored and redacted perfectly, and rendered "This activity type has no renderer" — and `GapSelectData` was not exported from lk-core's public barrel, so a consumer could not even name the type to write a renderer of their own. Both are closed here.
20
+
21
+ **`<GapSelect>`**, also at `@intellectif/lk-react/components/GapSelect`: a selector per `{{id}}` gap, the passage flowing around them. It carries the same contract as the other three built-ins — `value`/`defaultValue`/`onChange`, `practice | exam | review`, `defaultSubmitted`, `outcome`, dev-only boundary validation, reset-on-`data`-change, per-gap marking and authored feedback with a show/hide toggle, and the same render-time refusal of redacted data in `practice` that `<MultipleChoice>` and `<FillInTheBlanks>` make.
22
+
23
+ **The empty first entry is behaviour, not chrome.** It is how a learner leaves a gap alone and how they take an answer back, so an unanswered gap stays distinguishable from a wrong one: the scorer reports `incorrect-omission` and nothing downstream has to guess.
24
+
25
+ `shuffleChoices` is seeded **per gap**, not once per activity — two gaps drawing on one word bank must not be dealt the same order, or the bank's distractors line up column-wise and the second gap is easier than the first. `<ActivitySequence>`'s seed guard now counts `shuffleChoices` alongside `MultipleChoiceData.shuffle`, so an exam that shuffles without a `shuffleSeed` still throws at render.
26
+
27
+ Dispatch is wired in `<ActivitySequence>` and `<ActivityPreview>`, and a test renders a gap-select item through the sequence and asserts the unsupported notice is not what comes back — the gate that was missing when the type shipped half-built.
28
+
29
+ `LkStrings` gains `gapLabel(ordinal)` and `gapPlaceholder`. A dictionary declared as a complete `LkStrings` must add both; partial overrides are unaffected.
30
+
31
+ lk-core's patch is the public type export (`GapSelectData`, `GapSelectGap`, `GapSelectBank`, `GapSelectChoice`, `GapSelectLearnerResponse`) — no behaviour changes.
32
+
3
33
  ## 0.10.0
4
34
 
5
35
  ### Minor Changes
@@ -1020,4 +1020,4 @@ interface InteractionEvent {
1020
1020
  payload: Record<string, unknown>;
1021
1021
  }
1022
1022
 
1023
- export { type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type XAPIContextActivities as E, type FillInTheBlanksData as F, type GradeRecord as G, type XAPIError as H, type InlineCorrection as I, type XAPIObject as J, type XAPIResult as K, type LearnerResponse as L, type MultipleChoiceData as M, type NativeControlHint as N, type XAPIScore as O, type XAPIStatement as P, type XAPIVerbObject as Q, levenshteinDistance as R, type ScoringDetail as S, type TextMatchPolicy as T, matchText as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type ActivityDataMap as a, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type FillInTheBlanksLearnerResponse as f, type Grader as g, type GraderKind as h, type GraderUsage as i, type GradingState as j, type InteractionEvent as k, type InteractionKind as l, type ItemOutcome as m, type LearnerResponseMap as n, type MultipleChoiceLearnerResponse as o, type MultipleChoiceOption as p, type MultipleChoiceOptionMedia as q, type ScoringOutcome as r, type ScoringResult as s, type TextMatchResult as t, type ValidationResult as u, type WrittenResponseLearnerResponse as v, type WrittenResponseRubric as w, type WrittenResponseRubricCriterion as x, type XAPIConfig as y, type XAPIContext as z };
1023
+ export { levenshteinDistance as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type WrittenResponseLearnerResponse as E, type FillInTheBlanksData as F, type GapSelectBank as G, type WrittenResponseRubric as H, type InlineCorrection as I, type WrittenResponseRubricCriterion as J, type XAPIConfig as K, type LearnerResponse as L, type MultipleChoiceData as M, type NativeControlHint as N, type XAPIContext as O, type XAPIContextActivities as P, type XAPIError as Q, type XAPIObject as R, type ScoringDetail as S, type TextMatchPolicy as T, type XAPIResult as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type XAPIScore as Y, type XAPIStatement as Z, type XAPIVerbObject as _, type ActivityDataMap as a, matchText as a0, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type FillInTheBlanksLearnerResponse as f, type GapSelectChoice as g, type GapSelectData as h, type GapSelectGap as i, type GapSelectLearnerResponse as j, type GradeRecord as k, type Grader as l, type GraderKind as m, type GraderUsage as n, type GradingState as o, type InteractionEvent as p, type InteractionKind as q, type ItemOutcome as r, type LearnerResponseMap as s, type MultipleChoiceLearnerResponse as t, type MultipleChoiceOption as u, type MultipleChoiceOptionMedia as v, type ScoringOutcome as w, type ScoringResult as x, type TextMatchResult as y, type ValidationResult as z };
@@ -1020,4 +1020,4 @@ interface InteractionEvent {
1020
1020
  payload: Record<string, unknown>;
1021
1021
  }
1022
1022
 
1023
- export { type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type XAPIContextActivities as E, type FillInTheBlanksData as F, type GradeRecord as G, type XAPIError as H, type InlineCorrection as I, type XAPIObject as J, type XAPIResult as K, type LearnerResponse as L, type MultipleChoiceData as M, type NativeControlHint as N, type XAPIScore as O, type XAPIStatement as P, type XAPIVerbObject as Q, levenshteinDistance as R, type ScoringDetail as S, type TextMatchPolicy as T, matchText as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type ActivityDataMap as a, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type FillInTheBlanksLearnerResponse as f, type Grader as g, type GraderKind as h, type GraderUsage as i, type GradingState as j, type InteractionEvent as k, type InteractionKind as l, type ItemOutcome as m, type LearnerResponseMap as n, type MultipleChoiceLearnerResponse as o, type MultipleChoiceOption as p, type MultipleChoiceOptionMedia as q, type ScoringOutcome as r, type ScoringResult as s, type TextMatchResult as t, type ValidationResult as u, type WrittenResponseLearnerResponse as v, type WrittenResponseRubric as w, type WrittenResponseRubricCriterion as x, type XAPIConfig as y, type XAPIContext as z };
1023
+ export { levenshteinDistance as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type WrittenResponseLearnerResponse as E, type FillInTheBlanksData as F, type GapSelectBank as G, type WrittenResponseRubric as H, type InlineCorrection as I, type WrittenResponseRubricCriterion as J, type XAPIConfig as K, type LearnerResponse as L, type MultipleChoiceData as M, type NativeControlHint as N, type XAPIContext as O, type XAPIContextActivities as P, type XAPIError as Q, type XAPIObject as R, type ScoringDetail as S, type TextMatchPolicy as T, type XAPIResult as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type XAPIScore as Y, type XAPIStatement as Z, type XAPIVerbObject as _, type ActivityDataMap as a, matchText as a0, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type FillInTheBlanksLearnerResponse as f, type GapSelectChoice as g, type GapSelectData as h, type GapSelectGap as i, type GapSelectLearnerResponse as j, type GradeRecord as k, type Grader as l, type GraderKind as m, type GraderUsage as n, type GradingState as o, type InteractionEvent as p, type InteractionKind as q, type ItemOutcome as r, type LearnerResponseMap as s, type MultipleChoiceLearnerResponse as t, type MultipleChoiceOption as u, type MultipleChoiceOptionMedia as v, type ScoringOutcome as w, type ScoringResult as x, type TextMatchResult as y, type ValidationResult as z };
@@ -1,4 +1,4 @@
1
- import { A as ActivityData, c as ActivityMedia, u as ValidationResult, e as ActivityType, a as ActivityDataMap } from './activity-B0zbvu18.cjs';
1
+ import { A as ActivityData, c as ActivityMedia, z as ValidationResult, e as ActivityType, a as ActivityDataMap } from './activity-B2QxK15j.cjs';
2
2
  import { z } from 'zod/v4';
3
3
 
4
4
  /** What a stimulus primarily is. Drives validation and layout, never scoring. */
@@ -1,4 +1,4 @@
1
- import { A as ActivityData, c as ActivityMedia, u as ValidationResult, e as ActivityType, a as ActivityDataMap } from './activity-B0zbvu18.js';
1
+ import { A as ActivityData, c as ActivityMedia, z as ValidationResult, e as ActivityType, a as ActivityDataMap } from './activity-B2QxK15j.js';
2
2
  import { z } from 'zod/v4';
3
3
 
4
4
  /** What a stimulus primarily is. Drives validation and layout, never scoring. */
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ScoredItem } from './scoring.cjs';
2
2
  export { AssessmentScore, AssessmentSectionInput, Band, CompositionPolicy, DEFAULT_PASS_THRESHOLD, PassFailureReason, RoundingMode, RoundingPolicy, SectionScore, classifyBand, composeAssessmentScore, computePassThreshold, evaluate, gte, roundGrade, score } from './scoring.cjs';
3
- import { m as ItemOutcome, A as ActivityData, L as LearnerResponse, V as ValidationError, e as ActivityType, a as ActivityDataMap, C as CriterionScore, G as GradeRecord, N as NativeControlHint, c as ActivityMedia, s as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, o as MultipleChoiceLearnerResponse, W as WrittenResponseData, v as WrittenResponseLearnerResponse } from './activity-B0zbvu18.cjs';
4
- export { b as ActivityFeedback, d as ActivityResult, B as BlankConfig, g as Grader, h as GraderKind, i as GraderUsage, j as GradingState, I as InlineCorrection, k as InteractionEvent, l as InteractionKind, n as LearnerResponseMap, p as MultipleChoiceOption, q as MultipleChoiceOptionMedia, S as ScoringDetail, r as ScoringOutcome, T as TextMatchPolicy, t as TextMatchResult, u as ValidationResult, w as WrittenResponseRubric, x as WrittenResponseRubricCriterion, X as XAPIActor, y as XAPIConfig, z as XAPIContext, E as XAPIContextActivities, H as XAPIError, J as XAPIObject, K as XAPIResult, O as XAPIScore, P as XAPIStatement, Q as XAPIVerbObject, R as levenshteinDistance, U as matchText } from './activity-B0zbvu18.cjs';
5
- import { O as SequenceSlot, S as SequenceEntry, I as ItemGroup } from './index-u_rBLkuc.cjs';
6
- export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, P as SequenceSlotGroup, Q as Stimulus, T as StimulusKind, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-u_rBLkuc.cjs';
3
+ import { r as ItemOutcome, A as ActivityData, L as LearnerResponse, V as ValidationError, e as ActivityType, a as ActivityDataMap, C as CriterionScore, k as GradeRecord, N as NativeControlHint, c as ActivityMedia, x as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, t as MultipleChoiceLearnerResponse, W as WrittenResponseData, E as WrittenResponseLearnerResponse } from './activity-B2QxK15j.cjs';
4
+ export { b as ActivityFeedback, d as ActivityResult, B as BlankConfig, G as GapSelectBank, g as GapSelectChoice, h as GapSelectData, i as GapSelectGap, j as GapSelectLearnerResponse, l as Grader, m as GraderKind, n as GraderUsage, o as GradingState, I as InlineCorrection, p as InteractionEvent, q as InteractionKind, s as LearnerResponseMap, u as MultipleChoiceOption, v as MultipleChoiceOptionMedia, S as ScoringDetail, w as ScoringOutcome, T as TextMatchPolicy, y as TextMatchResult, z as ValidationResult, H as WrittenResponseRubric, J as WrittenResponseRubricCriterion, X as XAPIActor, K as XAPIConfig, O as XAPIContext, P as XAPIContextActivities, Q as XAPIError, R as XAPIObject, U as XAPIResult, Y as XAPIScore, Z as XAPIStatement, _ as XAPIVerbObject, $ as levenshteinDistance, a0 as matchText } from './activity-B2QxK15j.cjs';
5
+ import { O as SequenceSlot, S as SequenceEntry, I as ItemGroup } from './index-B_scInLM.cjs';
6
+ export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, P as SequenceSlotGroup, Q as Stimulus, T as StimulusKind, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-B_scInLM.cjs';
7
7
  import { z } from 'zod/v4';
8
8
  export { AnsweredStatementParams, CompletedStatementParams, SubmittedStatementParams, XAPIObjectParams, XAPIStatementParams, XAPIVerb, XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder, xapiDefinitionFor } from './xapi.cjs';
9
9
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ScoredItem } from './scoring.js';
2
2
  export { AssessmentScore, AssessmentSectionInput, Band, CompositionPolicy, DEFAULT_PASS_THRESHOLD, PassFailureReason, RoundingMode, RoundingPolicy, SectionScore, classifyBand, composeAssessmentScore, computePassThreshold, evaluate, gte, roundGrade, score } from './scoring.js';
3
- import { m as ItemOutcome, A as ActivityData, L as LearnerResponse, V as ValidationError, e as ActivityType, a as ActivityDataMap, C as CriterionScore, G as GradeRecord, N as NativeControlHint, c as ActivityMedia, s as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, o as MultipleChoiceLearnerResponse, W as WrittenResponseData, v as WrittenResponseLearnerResponse } from './activity-B0zbvu18.js';
4
- export { b as ActivityFeedback, d as ActivityResult, B as BlankConfig, g as Grader, h as GraderKind, i as GraderUsage, j as GradingState, I as InlineCorrection, k as InteractionEvent, l as InteractionKind, n as LearnerResponseMap, p as MultipleChoiceOption, q as MultipleChoiceOptionMedia, S as ScoringDetail, r as ScoringOutcome, T as TextMatchPolicy, t as TextMatchResult, u as ValidationResult, w as WrittenResponseRubric, x as WrittenResponseRubricCriterion, X as XAPIActor, y as XAPIConfig, z as XAPIContext, E as XAPIContextActivities, H as XAPIError, J as XAPIObject, K as XAPIResult, O as XAPIScore, P as XAPIStatement, Q as XAPIVerbObject, R as levenshteinDistance, U as matchText } from './activity-B0zbvu18.js';
5
- import { O as SequenceSlot, S as SequenceEntry, I as ItemGroup } from './index-DSfETm4b.js';
6
- export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, P as SequenceSlotGroup, Q as Stimulus, T as StimulusKind, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-DSfETm4b.js';
3
+ import { r as ItemOutcome, A as ActivityData, L as LearnerResponse, V as ValidationError, e as ActivityType, a as ActivityDataMap, C as CriterionScore, k as GradeRecord, N as NativeControlHint, c as ActivityMedia, x as ScoringResult, D as DeferredScoringPartial, F as FillInTheBlanksData, f as FillInTheBlanksLearnerResponse, M as MultipleChoiceData, t as MultipleChoiceLearnerResponse, W as WrittenResponseData, E as WrittenResponseLearnerResponse } from './activity-B2QxK15j.js';
4
+ export { b as ActivityFeedback, d as ActivityResult, B as BlankConfig, G as GapSelectBank, g as GapSelectChoice, h as GapSelectData, i as GapSelectGap, j as GapSelectLearnerResponse, l as Grader, m as GraderKind, n as GraderUsage, o as GradingState, I as InlineCorrection, p as InteractionEvent, q as InteractionKind, s as LearnerResponseMap, u as MultipleChoiceOption, v as MultipleChoiceOptionMedia, S as ScoringDetail, w as ScoringOutcome, T as TextMatchPolicy, y as TextMatchResult, z as ValidationResult, H as WrittenResponseRubric, J as WrittenResponseRubricCriterion, X as XAPIActor, K as XAPIConfig, O as XAPIContext, P as XAPIContextActivities, Q as XAPIError, R as XAPIObject, U as XAPIResult, Y as XAPIScore, Z as XAPIStatement, _ as XAPIVerbObject, $ as levenshteinDistance, a0 as matchText } from './activity-B2QxK15j.js';
5
+ import { O as SequenceSlot, S as SequenceEntry, I as ItemGroup } from './index-CRKtWP5G.js';
6
+ export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, P as SequenceSlotGroup, Q as Stimulus, T as StimulusKind, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-CRKtWP5G.js';
7
7
  import { z } from 'zod/v4';
8
8
  export { AnsweredStatementParams, CompletedStatementParams, SubmittedStatementParams, XAPIObjectParams, XAPIStatementParams, XAPIVerb, XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder, xapiDefinitionFor } from './xapi.js';
9
9
 
@@ -1,3 +1,3 @@
1
- import './activity-B0zbvu18.cjs';
2
- export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-u_rBLkuc.cjs';
1
+ import './activity-B2QxK15j.cjs';
2
+ export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-B_scInLM.cjs';
3
3
  import 'zod/v4';
package/dist/schemas.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import './activity-B0zbvu18.js';
2
- export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-DSfETm4b.js';
1
+ import './activity-B2QxK15j.js';
2
+ export { B as BlankConfigSchema, F as FeedbackSchema, a as FillInTheBlanksDataSchema, G as GapSelectBankSchema, b as GapSelectChoiceSchema, c as GapSelectDataSchema, d as GapSelectGapSchema, e as ItemGroupSchema, M as MediaPlaybackSchema, f as MediaSchema, g as MediaUrlSchema, h as MultipleChoiceDataSchema, i as MultipleChoiceOptionMediaSchema, j as MultipleChoiceOptionSchema, N as NativeControlHintSchema, R as RedactedActivity, k as RedactedBlankConfig, l as RedactedBlankConfigSchema, m as RedactedFillInTheBlanksData, n as RedactedFillInTheBlanksDataSchema, o as RedactedGapSelectBank, p as RedactedGapSelectBankSchema, q as RedactedGapSelectChoice, r as RedactedGapSelectChoiceSchema, s as RedactedGapSelectData, t as RedactedGapSelectDataSchema, u as RedactedGapSelectGap, v as RedactedGapSelectGapSchema, w as RedactedItemGroupSchema, x as RedactedMediaSchema, y as RedactedMultipleChoiceData, z as RedactedMultipleChoiceDataSchema, A as RedactedMultipleChoiceOption, C as RedactedMultipleChoiceOptionMedia, D as RedactedMultipleChoiceOptionMediaSchema, E as RedactedMultipleChoiceOptionSchema, H as RedactedStimulus, J as RedactedStimulusSchema, K as RedactedWrittenResponseData, L as RedactedWrittenResponseDataSchema, U as StimulusSchema, V as TextMatchPolicySchema, W as WrittenResponseDataSchema, X as WrittenResponseRubricCriterionSchema, Y as WrittenResponseRubricSchema, Z as fillInTheBlanksJsonSchema, _ as gapSelectJsonSchema, $ as itemGroupJsonSchema, a0 as jsonSchemaFor, a1 as multipleChoiceJsonSchema, a2 as stimulusJsonSchema, a3 as validateActivity, a4 as validateItemGroup, a5 as writtenResponseJsonSchema } from './index-CRKtWP5G.js';
3
3
  import 'zod/v4';
@@ -1,5 +1,5 @@
1
- import { m as ItemOutcome, A as ActivityData, L as LearnerResponse, e as ActivityType, s as ScoringResult } from './activity-B0zbvu18.cjs';
2
- export { T as TextMatchPolicy, t as TextMatchResult, R as levenshteinDistance, U as matchText } from './activity-B0zbvu18.cjs';
1
+ import { r as ItemOutcome, A as ActivityData, L as LearnerResponse, e as ActivityType, x as ScoringResult } from './activity-B2QxK15j.cjs';
2
+ export { T as TextMatchPolicy, y as TextMatchResult, $ as levenshteinDistance, a0 as matchText } from './activity-B2QxK15j.cjs';
3
3
 
4
4
  /**
5
5
  * Rounding for assessment scores.
package/dist/scoring.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { m as ItemOutcome, A as ActivityData, L as LearnerResponse, e as ActivityType, s as ScoringResult } from './activity-B0zbvu18.js';
2
- export { T as TextMatchPolicy, t as TextMatchResult, R as levenshteinDistance, U as matchText } from './activity-B0zbvu18.js';
1
+ import { r as ItemOutcome, A as ActivityData, L as LearnerResponse, e as ActivityType, x as ScoringResult } from './activity-B2QxK15j.js';
2
+ export { T as TextMatchPolicy, y as TextMatchResult, $ as levenshteinDistance, a0 as matchText } from './activity-B2QxK15j.js';
3
3
 
4
4
  /**
5
5
  * Rounding for assessment scores.
package/dist/xapi.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { X as XAPIActor, s as ScoringResult, z as XAPIContext, K as XAPIResult, P as XAPIStatement } from './activity-B0zbvu18.cjs';
1
+ import { X as XAPIActor, x as ScoringResult, O as XAPIContext, U as XAPIResult, Z as XAPIStatement } from './activity-B2QxK15j.cjs';
2
2
 
3
3
  /**
4
4
  * The set of xAPI verbs emitted by SDK activities, keyed by a stable
package/dist/xapi.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { X as XAPIActor, s as ScoringResult, z as XAPIContext, K as XAPIResult, P as XAPIStatement } from './activity-B0zbvu18.js';
1
+ import { X as XAPIActor, x as ScoringResult, O as XAPIContext, U as XAPIResult, Z as XAPIStatement } from './activity-B2QxK15j.js';
2
2
 
3
3
  /**
4
4
  * The set of xAPI verbs emitted by SDK activities, keyed by a stable
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectif/lk-core",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Framework-free assessment core: Zod activity schemas, pure scoring, rubric & deferred grading, weighted assessment composition, exam attempt plans, and xAPI 1.0.3.",
5
5
  "keywords": [
6
6
  "assessment",
@@ -92,7 +92,7 @@
92
92
  "license": "MIT",
93
93
  "sideEffects": false,
94
94
  "engines": {
95
- "node": ">=20"
95
+ "node": ">=22"
96
96
  },
97
97
  "scripts": {
98
98
  "build": "tsup",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$comment": "Grade-stability corpus for @intellectif/lk-core. Generated by scripts/generate-vectors.mjs from the built package; never edit expectations by hand. Replay with vectors/replay.mjs. See vectors/README.md.",
3
3
  "corpusVersion": 1,
4
- "frozenFrom": "@intellectif/lk-core@0.8.1",
4
+ "frozenFrom": "@intellectif/lk-core@0.10.1",
5
5
  "vectors": [
6
6
  {
7
7
  "args": [
@@ -1319,6 +1319,861 @@
1319
1319
  "id": "score/fib/partial/two-of-three",
1320
1320
  "note": "A non-terminating ratio (2/3), pinned exactly rather than approximately."
1321
1321
  },
1322
+ {
1323
+ "args": [
1324
+ "fill-in-the-blanks",
1325
+ {
1326
+ "blanks": [
1327
+ {
1328
+ "acceptedAnswers": ["a"],
1329
+ "id": "b1"
1330
+ },
1331
+ {
1332
+ "acceptedAnswers": ["the"],
1333
+ "id": "b2"
1334
+ },
1335
+ {
1336
+ "acceptedAnswers": ["the"],
1337
+ "id": "b3"
1338
+ }
1339
+ ],
1340
+ "id": "fib-articles",
1341
+ "passage": "We bought {{b1}} lamp for {{b2}} study and {{b3}} hall.",
1342
+ "schemaVersion": "1.0",
1343
+ "scoringStrategy": "all-or-nothing",
1344
+ "title": "Articles",
1345
+ "type": "fill-in-the-blanks"
1346
+ },
1347
+ {
1348
+ "answers": {
1349
+ "b1": "a",
1350
+ "b2": "the",
1351
+ "b3": "the"
1352
+ },
1353
+ "type": "fill-in-the-blanks"
1354
+ }
1355
+ ],
1356
+ "expect": {
1357
+ "details": [
1358
+ {
1359
+ "correct": true,
1360
+ "correctResponse": ["a"],
1361
+ "itemId": "b1",
1362
+ "learnerResponse": ["a"],
1363
+ "outcome": "correct",
1364
+ "weight": 1
1365
+ },
1366
+ {
1367
+ "correct": true,
1368
+ "correctResponse": ["the"],
1369
+ "itemId": "b2",
1370
+ "learnerResponse": ["the"],
1371
+ "outcome": "correct",
1372
+ "weight": 1
1373
+ },
1374
+ {
1375
+ "correct": true,
1376
+ "correctResponse": ["the"],
1377
+ "itemId": "b3",
1378
+ "learnerResponse": ["the"],
1379
+ "outcome": "correct",
1380
+ "weight": 1
1381
+ }
1382
+ ],
1383
+ "feedback": null,
1384
+ "maxScore": 1,
1385
+ "passed": true,
1386
+ "score": 1
1387
+ },
1388
+ "fn": "score",
1389
+ "id": "score/fib/all-or-nothing/every-blank-right"
1390
+ },
1391
+ {
1392
+ "args": [
1393
+ "fill-in-the-blanks",
1394
+ {
1395
+ "blanks": [],
1396
+ "id": "fib-articles",
1397
+ "passage": "Nothing to fill.",
1398
+ "schemaVersion": "1.0",
1399
+ "scoringStrategy": "all-or-nothing",
1400
+ "title": "Articles",
1401
+ "type": "fill-in-the-blanks"
1402
+ },
1403
+ {
1404
+ "answers": {},
1405
+ "type": "fill-in-the-blanks"
1406
+ }
1407
+ ],
1408
+ "expect": {
1409
+ "details": [],
1410
+ "feedback": null,
1411
+ "maxScore": 1,
1412
+ "passed": true,
1413
+ "score": 1
1414
+ },
1415
+ "fn": "score",
1416
+ "id": "score/fib/all-or-nothing/empty-blank-list"
1417
+ },
1418
+ {
1419
+ "args": [
1420
+ "gap-select",
1421
+ {
1422
+ "banks": [
1423
+ {
1424
+ "choices": [
1425
+ {
1426
+ "id": "of",
1427
+ "text": "of"
1428
+ },
1429
+ {
1430
+ "id": "from",
1431
+ "text": "from"
1432
+ },
1433
+ {
1434
+ "id": "to",
1435
+ "text": "to"
1436
+ },
1437
+ {
1438
+ "id": "on",
1439
+ "text": "on"
1440
+ }
1441
+ ],
1442
+ "id": "prep"
1443
+ }
1444
+ ],
1445
+ "gaps": [
1446
+ {
1447
+ "bankId": "prep",
1448
+ "correctChoiceId": "from",
1449
+ "id": "a"
1450
+ },
1451
+ {
1452
+ "bankId": "prep",
1453
+ "correctChoiceId": "from",
1454
+ "id": "b"
1455
+ }
1456
+ ],
1457
+ "id": "gs-prepositions",
1458
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1459
+ "schemaVersion": "1.0",
1460
+ "scoringStrategy": "partial",
1461
+ "title": "Prepositions",
1462
+ "type": "gap-select"
1463
+ },
1464
+ {
1465
+ "selections": {
1466
+ "a": "from",
1467
+ "b": "from"
1468
+ },
1469
+ "type": "gap-select"
1470
+ }
1471
+ ],
1472
+ "expect": {
1473
+ "details": [
1474
+ {
1475
+ "correct": true,
1476
+ "correctResponse": ["from"],
1477
+ "itemId": "a",
1478
+ "learnerResponse": ["from"],
1479
+ "outcome": "correct",
1480
+ "weight": 1
1481
+ },
1482
+ {
1483
+ "correct": true,
1484
+ "correctResponse": ["from"],
1485
+ "itemId": "b",
1486
+ "learnerResponse": ["from"],
1487
+ "outcome": "correct",
1488
+ "weight": 1
1489
+ }
1490
+ ],
1491
+ "feedback": null,
1492
+ "maxScore": 1,
1493
+ "passed": true,
1494
+ "score": 1
1495
+ },
1496
+ "fn": "score",
1497
+ "id": "score/gs/partial/both-right"
1498
+ },
1499
+ {
1500
+ "args": [
1501
+ "gap-select",
1502
+ {
1503
+ "banks": [
1504
+ {
1505
+ "choices": [
1506
+ {
1507
+ "id": "of",
1508
+ "text": "of"
1509
+ },
1510
+ {
1511
+ "id": "from",
1512
+ "text": "from"
1513
+ },
1514
+ {
1515
+ "id": "to",
1516
+ "text": "to"
1517
+ },
1518
+ {
1519
+ "id": "on",
1520
+ "text": "on"
1521
+ }
1522
+ ],
1523
+ "id": "prep"
1524
+ }
1525
+ ],
1526
+ "gaps": [
1527
+ {
1528
+ "bankId": "prep",
1529
+ "correctChoiceId": "from",
1530
+ "id": "a"
1531
+ },
1532
+ {
1533
+ "bankId": "prep",
1534
+ "correctChoiceId": "from",
1535
+ "id": "b"
1536
+ }
1537
+ ],
1538
+ "id": "gs-prepositions",
1539
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1540
+ "schemaVersion": "1.0",
1541
+ "scoringStrategy": "partial",
1542
+ "title": "Prepositions",
1543
+ "type": "gap-select"
1544
+ },
1545
+ {
1546
+ "selections": {
1547
+ "a": "from",
1548
+ "b": "to"
1549
+ },
1550
+ "type": "gap-select"
1551
+ }
1552
+ ],
1553
+ "expect": {
1554
+ "details": [
1555
+ {
1556
+ "correct": true,
1557
+ "correctResponse": ["from"],
1558
+ "itemId": "a",
1559
+ "learnerResponse": ["from"],
1560
+ "outcome": "correct",
1561
+ "weight": 1
1562
+ },
1563
+ {
1564
+ "correct": false,
1565
+ "correctResponse": ["from"],
1566
+ "itemId": "b",
1567
+ "learnerResponse": ["to"],
1568
+ "outcome": "incorrect",
1569
+ "weight": 1
1570
+ }
1571
+ ],
1572
+ "feedback": null,
1573
+ "maxScore": 1,
1574
+ "passed": false,
1575
+ "score": 0.5
1576
+ },
1577
+ "fn": "score",
1578
+ "id": "score/gs/partial/one-right"
1579
+ },
1580
+ {
1581
+ "args": [
1582
+ "gap-select",
1583
+ {
1584
+ "banks": [
1585
+ {
1586
+ "choices": [
1587
+ {
1588
+ "id": "of",
1589
+ "text": "of"
1590
+ },
1591
+ {
1592
+ "id": "from",
1593
+ "text": "from"
1594
+ },
1595
+ {
1596
+ "id": "to",
1597
+ "text": "to"
1598
+ },
1599
+ {
1600
+ "id": "on",
1601
+ "text": "on"
1602
+ }
1603
+ ],
1604
+ "id": "prep"
1605
+ }
1606
+ ],
1607
+ "gaps": [
1608
+ {
1609
+ "bankId": "prep",
1610
+ "correctChoiceId": "from",
1611
+ "id": "a"
1612
+ },
1613
+ {
1614
+ "bankId": "prep",
1615
+ "correctChoiceId": "from",
1616
+ "id": "b"
1617
+ }
1618
+ ],
1619
+ "id": "gs-prepositions",
1620
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1621
+ "schemaVersion": "1.0",
1622
+ "scoringStrategy": "partial",
1623
+ "title": "Prepositions",
1624
+ "type": "gap-select"
1625
+ },
1626
+ {
1627
+ "selections": {
1628
+ "a": "from"
1629
+ },
1630
+ "type": "gap-select"
1631
+ }
1632
+ ],
1633
+ "expect": {
1634
+ "details": [
1635
+ {
1636
+ "correct": true,
1637
+ "correctResponse": ["from"],
1638
+ "itemId": "a",
1639
+ "learnerResponse": ["from"],
1640
+ "outcome": "correct",
1641
+ "weight": 1
1642
+ },
1643
+ {
1644
+ "correct": false,
1645
+ "correctResponse": ["from"],
1646
+ "itemId": "b",
1647
+ "learnerResponse": [""],
1648
+ "outcome": "incorrect-omission",
1649
+ "weight": 1
1650
+ }
1651
+ ],
1652
+ "feedback": null,
1653
+ "maxScore": 1,
1654
+ "passed": false,
1655
+ "score": 0.5
1656
+ },
1657
+ "fn": "score",
1658
+ "id": "score/gs/partial/unanswered-gap"
1659
+ },
1660
+ {
1661
+ "args": [
1662
+ "gap-select",
1663
+ {
1664
+ "banks": [
1665
+ {
1666
+ "choices": [
1667
+ {
1668
+ "id": "of",
1669
+ "text": "of"
1670
+ },
1671
+ {
1672
+ "id": "from",
1673
+ "text": "from"
1674
+ },
1675
+ {
1676
+ "id": "to",
1677
+ "text": "to"
1678
+ },
1679
+ {
1680
+ "id": "on",
1681
+ "text": "on"
1682
+ }
1683
+ ],
1684
+ "id": "prep"
1685
+ }
1686
+ ],
1687
+ "gaps": [
1688
+ {
1689
+ "bankId": "prep",
1690
+ "correctChoiceId": "from",
1691
+ "id": "a"
1692
+ },
1693
+ {
1694
+ "bankId": "prep",
1695
+ "correctChoiceId": "from",
1696
+ "id": "b"
1697
+ }
1698
+ ],
1699
+ "id": "gs-prepositions",
1700
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1701
+ "schemaVersion": "1.0",
1702
+ "scoringStrategy": "partial",
1703
+ "title": "Prepositions",
1704
+ "type": "gap-select"
1705
+ },
1706
+ {
1707
+ "selections": {
1708
+ "a": "from",
1709
+ "b": ""
1710
+ },
1711
+ "type": "gap-select"
1712
+ }
1713
+ ],
1714
+ "expect": {
1715
+ "details": [
1716
+ {
1717
+ "correct": true,
1718
+ "correctResponse": ["from"],
1719
+ "itemId": "a",
1720
+ "learnerResponse": ["from"],
1721
+ "outcome": "correct",
1722
+ "weight": 1
1723
+ },
1724
+ {
1725
+ "correct": false,
1726
+ "correctResponse": ["from"],
1727
+ "itemId": "b",
1728
+ "learnerResponse": [""],
1729
+ "outcome": "incorrect-omission",
1730
+ "weight": 1
1731
+ }
1732
+ ],
1733
+ "feedback": null,
1734
+ "maxScore": 1,
1735
+ "passed": false,
1736
+ "score": 0.5
1737
+ },
1738
+ "fn": "score",
1739
+ "id": "score/gs/partial/empty-string-is-unanswered"
1740
+ },
1741
+ {
1742
+ "args": [
1743
+ "gap-select",
1744
+ {
1745
+ "banks": [
1746
+ {
1747
+ "choices": [
1748
+ {
1749
+ "id": "of",
1750
+ "text": "of"
1751
+ },
1752
+ {
1753
+ "id": "from",
1754
+ "text": "from"
1755
+ },
1756
+ {
1757
+ "id": "to",
1758
+ "text": "to"
1759
+ },
1760
+ {
1761
+ "id": "on",
1762
+ "text": "on"
1763
+ }
1764
+ ],
1765
+ "id": "prep"
1766
+ }
1767
+ ],
1768
+ "gaps": [
1769
+ {
1770
+ "bankId": "prep",
1771
+ "correctChoiceId": "from",
1772
+ "id": "a"
1773
+ },
1774
+ {
1775
+ "bankId": "prep",
1776
+ "correctChoiceId": "from",
1777
+ "id": "b"
1778
+ }
1779
+ ],
1780
+ "id": "gs-prepositions",
1781
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1782
+ "schemaVersion": "1.0",
1783
+ "scoringStrategy": "partial",
1784
+ "title": "Prepositions",
1785
+ "type": "gap-select"
1786
+ },
1787
+ {
1788
+ "selections": {
1789
+ "a": "smuggled",
1790
+ "b": "from"
1791
+ },
1792
+ "type": "gap-select"
1793
+ }
1794
+ ],
1795
+ "expect": {
1796
+ "details": [
1797
+ {
1798
+ "correct": false,
1799
+ "correctResponse": ["from"],
1800
+ "itemId": "a",
1801
+ "learnerResponse": ["smuggled"],
1802
+ "outcome": "incorrect-omission",
1803
+ "weight": 1
1804
+ },
1805
+ {
1806
+ "correct": true,
1807
+ "correctResponse": ["from"],
1808
+ "itemId": "b",
1809
+ "learnerResponse": ["from"],
1810
+ "outcome": "correct",
1811
+ "weight": 1
1812
+ }
1813
+ ],
1814
+ "feedback": null,
1815
+ "maxScore": 1,
1816
+ "passed": false,
1817
+ "score": 0.5
1818
+ },
1819
+ "fn": "score",
1820
+ "id": "score/gs/partial/choice-never-offered"
1821
+ },
1822
+ {
1823
+ "args": [
1824
+ "gap-select",
1825
+ {
1826
+ "banks": [
1827
+ {
1828
+ "choices": [
1829
+ {
1830
+ "id": "of",
1831
+ "text": "of"
1832
+ },
1833
+ {
1834
+ "id": "from",
1835
+ "text": "from"
1836
+ },
1837
+ {
1838
+ "id": "to",
1839
+ "text": "to"
1840
+ },
1841
+ {
1842
+ "id": "on",
1843
+ "text": "on"
1844
+ }
1845
+ ],
1846
+ "id": "prep"
1847
+ }
1848
+ ],
1849
+ "gaps": [
1850
+ {
1851
+ "bankId": "prep",
1852
+ "correctChoiceId": "from",
1853
+ "id": "a"
1854
+ },
1855
+ {
1856
+ "bankId": "prep",
1857
+ "correctChoiceId": "from",
1858
+ "id": "b"
1859
+ }
1860
+ ],
1861
+ "id": "gs-prepositions",
1862
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1863
+ "schemaVersion": "1.0",
1864
+ "scoringStrategy": "all-or-nothing",
1865
+ "title": "Prepositions",
1866
+ "type": "gap-select"
1867
+ },
1868
+ {
1869
+ "selections": {
1870
+ "a": "from",
1871
+ "b": "from"
1872
+ },
1873
+ "type": "gap-select"
1874
+ }
1875
+ ],
1876
+ "expect": {
1877
+ "details": [
1878
+ {
1879
+ "correct": true,
1880
+ "correctResponse": ["from"],
1881
+ "itemId": "a",
1882
+ "learnerResponse": ["from"],
1883
+ "outcome": "correct",
1884
+ "weight": 1
1885
+ },
1886
+ {
1887
+ "correct": true,
1888
+ "correctResponse": ["from"],
1889
+ "itemId": "b",
1890
+ "learnerResponse": ["from"],
1891
+ "outcome": "correct",
1892
+ "weight": 1
1893
+ }
1894
+ ],
1895
+ "feedback": null,
1896
+ "maxScore": 1,
1897
+ "passed": true,
1898
+ "score": 1
1899
+ },
1900
+ "fn": "score",
1901
+ "id": "score/gs/all-or-nothing/both-right"
1902
+ },
1903
+ {
1904
+ "args": [
1905
+ "gap-select",
1906
+ {
1907
+ "banks": [
1908
+ {
1909
+ "choices": [
1910
+ {
1911
+ "id": "of",
1912
+ "text": "of"
1913
+ },
1914
+ {
1915
+ "id": "from",
1916
+ "text": "from"
1917
+ },
1918
+ {
1919
+ "id": "to",
1920
+ "text": "to"
1921
+ },
1922
+ {
1923
+ "id": "on",
1924
+ "text": "on"
1925
+ }
1926
+ ],
1927
+ "id": "prep"
1928
+ }
1929
+ ],
1930
+ "gaps": [
1931
+ {
1932
+ "bankId": "prep",
1933
+ "correctChoiceId": "from",
1934
+ "id": "a"
1935
+ },
1936
+ {
1937
+ "bankId": "prep",
1938
+ "correctChoiceId": "from",
1939
+ "id": "b"
1940
+ }
1941
+ ],
1942
+ "id": "gs-prepositions",
1943
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
1944
+ "schemaVersion": "1.0",
1945
+ "scoringStrategy": "all-or-nothing",
1946
+ "title": "Prepositions",
1947
+ "type": "gap-select"
1948
+ },
1949
+ {
1950
+ "selections": {
1951
+ "a": "from",
1952
+ "b": "to"
1953
+ },
1954
+ "type": "gap-select"
1955
+ }
1956
+ ],
1957
+ "expect": {
1958
+ "details": [
1959
+ {
1960
+ "correct": true,
1961
+ "correctResponse": ["from"],
1962
+ "itemId": "a",
1963
+ "learnerResponse": ["from"],
1964
+ "outcome": "correct",
1965
+ "weight": 1
1966
+ },
1967
+ {
1968
+ "correct": false,
1969
+ "correctResponse": ["from"],
1970
+ "itemId": "b",
1971
+ "learnerResponse": ["to"],
1972
+ "outcome": "incorrect",
1973
+ "weight": 1
1974
+ }
1975
+ ],
1976
+ "feedback": null,
1977
+ "maxScore": 1,
1978
+ "passed": false,
1979
+ "score": 0
1980
+ },
1981
+ "fn": "score",
1982
+ "id": "score/gs/all-or-nothing/one-wrong"
1983
+ },
1984
+ {
1985
+ "args": [
1986
+ "gap-select",
1987
+ {
1988
+ "gaps": [
1989
+ {
1990
+ "choices": [
1991
+ {
1992
+ "id": "blue",
1993
+ "text": "blue"
1994
+ },
1995
+ {
1996
+ "id": "red",
1997
+ "text": "red"
1998
+ }
1999
+ ],
2000
+ "correctChoiceId": "blue",
2001
+ "id": "a"
2002
+ }
2003
+ ],
2004
+ "id": "gs-prepositions",
2005
+ "passage": "The sky is {{a}}.",
2006
+ "schemaVersion": "1.0",
2007
+ "scoringStrategy": "partial",
2008
+ "title": "Prepositions",
2009
+ "type": "gap-select"
2010
+ },
2011
+ {
2012
+ "selections": {
2013
+ "a": "blue"
2014
+ },
2015
+ "type": "gap-select"
2016
+ }
2017
+ ],
2018
+ "expect": {
2019
+ "details": [
2020
+ {
2021
+ "correct": true,
2022
+ "correctResponse": ["blue"],
2023
+ "itemId": "a",
2024
+ "learnerResponse": ["blue"],
2025
+ "outcome": "correct",
2026
+ "weight": 1
2027
+ }
2028
+ ],
2029
+ "feedback": null,
2030
+ "maxScore": 1,
2031
+ "passed": true,
2032
+ "score": 1
2033
+ },
2034
+ "fn": "score",
2035
+ "id": "score/gs/own-choices-not-a-bank"
2036
+ },
2037
+ {
2038
+ "args": [
2039
+ "gap-select",
2040
+ {
2041
+ "banks": [],
2042
+ "gaps": [
2043
+ {
2044
+ "bankId": "prep",
2045
+ "correctChoiceId": "from",
2046
+ "id": "a"
2047
+ },
2048
+ {
2049
+ "bankId": "prep",
2050
+ "correctChoiceId": "from",
2051
+ "id": "b"
2052
+ }
2053
+ ],
2054
+ "id": "gs-prepositions",
2055
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
2056
+ "schemaVersion": "1.0",
2057
+ "scoringStrategy": "partial",
2058
+ "title": "Prepositions",
2059
+ "type": "gap-select"
2060
+ },
2061
+ {
2062
+ "selections": {
2063
+ "a": "from",
2064
+ "b": "from"
2065
+ },
2066
+ "type": "gap-select"
2067
+ }
2068
+ ],
2069
+ "expect": {
2070
+ "details": [
2071
+ {
2072
+ "correct": false,
2073
+ "correctResponse": ["from"],
2074
+ "itemId": "a",
2075
+ "learnerResponse": ["from"],
2076
+ "outcome": "incorrect-omission",
2077
+ "weight": 1
2078
+ },
2079
+ {
2080
+ "correct": false,
2081
+ "correctResponse": ["from"],
2082
+ "itemId": "b",
2083
+ "learnerResponse": ["from"],
2084
+ "outcome": "incorrect-omission",
2085
+ "weight": 1
2086
+ }
2087
+ ],
2088
+ "feedback": null,
2089
+ "maxScore": 1,
2090
+ "passed": false,
2091
+ "score": 0
2092
+ },
2093
+ "fn": "score",
2094
+ "id": "score/gs/missing-bank-scores-zero"
2095
+ },
2096
+ {
2097
+ "args": [
2098
+ {
2099
+ "banks": [
2100
+ {
2101
+ "choices": [
2102
+ {
2103
+ "id": "of",
2104
+ "text": "of"
2105
+ },
2106
+ {
2107
+ "id": "from",
2108
+ "text": "from"
2109
+ },
2110
+ {
2111
+ "id": "to",
2112
+ "text": "to"
2113
+ },
2114
+ {
2115
+ "id": "on",
2116
+ "text": "on"
2117
+ }
2118
+ ],
2119
+ "id": "prep"
2120
+ }
2121
+ ],
2122
+ "gaps": [
2123
+ {
2124
+ "bankId": "prep",
2125
+ "correctChoiceId": "from",
2126
+ "id": "a"
2127
+ },
2128
+ {
2129
+ "bankId": "prep",
2130
+ "correctChoiceId": "from",
2131
+ "id": "b"
2132
+ }
2133
+ ],
2134
+ "id": "gs-prepositions",
2135
+ "passage": "Where are you {{a}}? I'm {{b}} Spain.",
2136
+ "schemaVersion": "1.0",
2137
+ "scoringStrategy": "partial",
2138
+ "title": "Prepositions",
2139
+ "type": "gap-select"
2140
+ },
2141
+ {
2142
+ "selections": {
2143
+ "a": "from",
2144
+ "b": "from"
2145
+ },
2146
+ "type": "gap-select"
2147
+ }
2148
+ ],
2149
+ "expect": {
2150
+ "details": [
2151
+ {
2152
+ "correct": true,
2153
+ "correctResponse": ["from"],
2154
+ "itemId": "a",
2155
+ "learnerResponse": ["from"],
2156
+ "outcome": "correct",
2157
+ "weight": 1
2158
+ },
2159
+ {
2160
+ "correct": true,
2161
+ "correctResponse": ["from"],
2162
+ "itemId": "b",
2163
+ "learnerResponse": ["from"],
2164
+ "outcome": "correct",
2165
+ "weight": 1
2166
+ }
2167
+ ],
2168
+ "feedback": null,
2169
+ "maxScore": 1,
2170
+ "passed": true,
2171
+ "score": 1,
2172
+ "status": "scored"
2173
+ },
2174
+ "fn": "evaluate",
2175
+ "id": "evaluate/gs/scored"
2176
+ },
1322
2177
  {
1323
2178
  "args": [
1324
2179
  "fill-in-the-blanks",
@@ -2838,6 +3693,51 @@
2838
3693
  "id": "matchText/policy/levenshtein-1-single-character-hazard",
2839
3694
  "note": "Deliberate and documented: distance 1 against a one-character answer accepts ANY single character."
2840
3695
  },
3696
+ {
3697
+ "args": ["a", "ab", 2],
3698
+ "expect": 1,
3699
+ "fn": "levenshteinDistance",
3700
+ "id": "levenshteinDistance/one-char-vs-longer"
3701
+ },
3702
+ {
3703
+ "args": ["ab", "a", 2],
3704
+ "expect": 1,
3705
+ "fn": "levenshteinDistance",
3706
+ "id": "levenshteinDistance/longer-vs-one-char"
3707
+ },
3708
+ {
3709
+ "args": ["a", "b", 2],
3710
+ "expect": 1,
3711
+ "fn": "levenshteinDistance",
3712
+ "id": "levenshteinDistance/one-char-each"
3713
+ },
3714
+ {
3715
+ "args": ["", "a", 2],
3716
+ "expect": 1,
3717
+ "fn": "levenshteinDistance",
3718
+ "id": "levenshteinDistance/empty-vs-one-char"
3719
+ },
3720
+ {
3721
+ "args": ["a", "", 2],
3722
+ "expect": 1,
3723
+ "fn": "levenshteinDistance",
3724
+ "id": "levenshteinDistance/one-char-vs-empty"
3725
+ },
3726
+ {
3727
+ "args": [
3728
+ "a",
3729
+ ["b"],
3730
+ {
3731
+ "levenshtein": 1
3732
+ }
3733
+ ],
3734
+ "expect": {
3735
+ "matched": true,
3736
+ "via": "fuzzy"
3737
+ },
3738
+ "fn": "matchText",
3739
+ "id": "matchText/levenshtein/one-char-typo"
3740
+ },
2841
3741
  {
2842
3742
  "args": ["kitten", "sitting", 10],
2843
3743
  "expect": 3,
@@ -4914,6 +5814,125 @@
4914
5814
  "fn": "outcomeFromGrade",
4915
5815
  "id": "outcomeFromGrade/lifts-a-grade"
4916
5816
  },
5817
+ {
5818
+ "args": [
5819
+ [
5820
+ {
5821
+ "id": "a",
5822
+ "items": [
5823
+ {
5824
+ "outcome": {
5825
+ "details": [],
5826
+ "feedback": null,
5827
+ "maxScore": 1,
5828
+ "passed": true,
5829
+ "score": 1,
5830
+ "status": "scored"
5831
+ },
5832
+ "points": 1,
5833
+ "slotId": "a1"
5834
+ }
5835
+ ],
5836
+ "title": "Reading",
5837
+ "weight": 1
5838
+ }
5839
+ ],
5840
+ {
5841
+ "passThreshold": 0.7,
5842
+ "rounding": {
5843
+ "dp": 2,
5844
+ "mode": "half-up"
5845
+ }
5846
+ }
5847
+ ],
5848
+ "expect": {
5849
+ "passFailureReason": null,
5850
+ "passed": true,
5851
+ "pendingSlotIds": [],
5852
+ "score": 1,
5853
+ "sections": [
5854
+ {
5855
+ "appliedThreshold": null,
5856
+ "earnedPoints": 1,
5857
+ "gradedMaxPoints": 1,
5858
+ "id": "a",
5859
+ "maxPoints": 1,
5860
+ "normalizedWeight": 1,
5861
+ "passed": true,
5862
+ "pendingSlotIds": [],
5863
+ "score": 1,
5864
+ "title": "Reading",
5865
+ "unscorableSlotIds": [],
5866
+ "weight": 1
5867
+ }
5868
+ ],
5869
+ "status": "final",
5870
+ "unscorableSlotIds": []
5871
+ },
5872
+ "fn": "composeAssessmentScore",
5873
+ "id": "composeAssessmentScore/section-with-title"
5874
+ },
5875
+ {
5876
+ "args": [
5877
+ [
5878
+ {
5879
+ "id": "a",
5880
+ "items": [
5881
+ {
5882
+ "outcome": {
5883
+ "feedback": null,
5884
+ "grade": {
5885
+ "feedback": null,
5886
+ "maxScore": 0.5,
5887
+ "passed": true,
5888
+ "score": 0.4
5889
+ },
5890
+ "maxScore": 0.5,
5891
+ "passed": true,
5892
+ "score": 0.4,
5893
+ "status": "graded"
5894
+ },
5895
+ "points": 1,
5896
+ "slotId": "a1"
5897
+ }
5898
+ ],
5899
+ "weight": 1
5900
+ }
5901
+ ],
5902
+ {
5903
+ "passThreshold": 0.7,
5904
+ "rounding": {
5905
+ "dp": 2,
5906
+ "mode": "half-up"
5907
+ }
5908
+ }
5909
+ ],
5910
+ "expect": {
5911
+ "passFailureReason": null,
5912
+ "passed": true,
5913
+ "pendingSlotIds": [],
5914
+ "score": 0.8,
5915
+ "sections": [
5916
+ {
5917
+ "appliedThreshold": null,
5918
+ "earnedPoints": 0.8,
5919
+ "gradedMaxPoints": 1,
5920
+ "id": "a",
5921
+ "maxPoints": 1,
5922
+ "normalizedWeight": 1,
5923
+ "passed": true,
5924
+ "pendingSlotIds": [],
5925
+ "score": 0.8,
5926
+ "unscorableSlotIds": [],
5927
+ "weight": 1
5928
+ }
5929
+ ],
5930
+ "status": "final",
5931
+ "unscorableSlotIds": []
5932
+ },
5933
+ "fn": "composeAssessmentScore",
5934
+ "id": "composeAssessmentScore/graded/max-score-below-one"
5935
+ },
4917
5936
  {
4918
5937
  "args": [
4919
5938
  [