@intellectif/lk-core 0.22.0 → 1.1.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 (66) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +6 -6
  3. package/dist/{activity-CYc7SD3d.d.cts → activity-MBOYLBjR.d.cts} +128 -22
  4. package/dist/{activity-CYc7SD3d.d.ts → activity-MBOYLBjR.d.ts} +128 -22
  5. package/dist/ai-check.cjs +138 -9
  6. package/dist/ai-check.cjs.map +1 -1
  7. package/dist/ai-check.d.cts +6 -3
  8. package/dist/ai-check.d.ts +6 -3
  9. package/dist/ai-check.js +133 -4
  10. package/dist/ai-check.js.map +1 -1
  11. package/dist/{chunk-2CV6NU32.cjs → chunk-2JT2WUQ2.cjs} +77 -39
  12. package/dist/chunk-2JT2WUQ2.cjs.map +1 -0
  13. package/dist/{chunk-D4TOPSHV.cjs → chunk-DSDXL3JO.cjs} +1216 -1105
  14. package/dist/chunk-DSDXL3JO.cjs.map +1 -0
  15. package/dist/{chunk-D3GP5MET.js → chunk-FBKTION6.js} +1093 -982
  16. package/dist/chunk-FBKTION6.js.map +1 -0
  17. package/dist/{chunk-Q7MV3IXJ.js → chunk-IARLJ5MW.js} +15 -16
  18. package/dist/chunk-IARLJ5MW.js.map +1 -0
  19. package/dist/{chunk-OPMY2MNS.cjs → chunk-LDFQUZII.cjs} +248 -22
  20. package/dist/chunk-LDFQUZII.cjs.map +1 -0
  21. package/dist/{chunk-5UCR4UNR.js → chunk-NQHETFDA.js} +238 -12
  22. package/dist/chunk-NQHETFDA.js.map +1 -0
  23. package/dist/{chunk-X5DAXBJI.js → chunk-SJVRUPJT.js} +2 -2
  24. package/dist/{chunk-EOFWSGLU.cjs → chunk-TJJFKKH2.cjs} +4 -4
  25. package/dist/{chunk-EOFWSGLU.cjs.map → chunk-TJJFKKH2.cjs.map} +1 -1
  26. package/dist/{chunk-WQVZPIN7.cjs → chunk-VSH7ECQL.cjs} +44 -45
  27. package/dist/chunk-VSH7ECQL.cjs.map +1 -0
  28. package/dist/{chunk-Z7QQZ53L.js → chunk-XS6U2ARZ.js} +70 -32
  29. package/dist/chunk-XS6U2ARZ.js.map +1 -0
  30. package/dist/index-DlCW0XaQ.d.cts +548 -0
  31. package/dist/index-DlcqkM_L.d.ts +548 -0
  32. package/dist/index.cjs +129 -198
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +178 -21
  35. package/dist/index.d.ts +178 -21
  36. package/dist/index.js +34 -103
  37. package/dist/index.js.map +1 -1
  38. package/dist/schemas.cjs +3 -94
  39. package/dist/schemas.cjs.map +1 -1
  40. package/dist/schemas.d.cts +2 -3
  41. package/dist/schemas.d.ts +2 -3
  42. package/dist/schemas.js +6 -97
  43. package/dist/scoring.cjs +3 -3
  44. package/dist/scoring.d.cts +242 -242
  45. package/dist/scoring.d.ts +242 -242
  46. package/dist/scoring.js +2 -2
  47. package/dist/xapi.cjs +3 -3
  48. package/dist/xapi.d.cts +1 -1
  49. package/dist/xapi.d.ts +1 -1
  50. package/dist/xapi.js +2 -2
  51. package/package.json +4 -4
  52. package/vectors/README.md +32 -2
  53. package/vectors/scoring.json +1 -498
  54. package/vectors/validation.json +6742 -0
  55. package/vectors/validation.mjs +195 -0
  56. package/dist/chunk-2CV6NU32.cjs.map +0 -1
  57. package/dist/chunk-5UCR4UNR.js.map +0 -1
  58. package/dist/chunk-D3GP5MET.js.map +0 -1
  59. package/dist/chunk-D4TOPSHV.cjs.map +0 -1
  60. package/dist/chunk-OPMY2MNS.cjs.map +0 -1
  61. package/dist/chunk-Q7MV3IXJ.js.map +0 -1
  62. package/dist/chunk-WQVZPIN7.cjs.map +0 -1
  63. package/dist/chunk-Z7QQZ53L.js.map +0 -1
  64. package/dist/index-0Z3-nnAP.d.ts +0 -2303
  65. package/dist/index-CxxiNSSH.d.cts +0 -2303
  66. /package/dist/{chunk-X5DAXBJI.js.map → chunk-SJVRUPJT.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @intellectif/lk-core
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#86](https://github.com/intellectif/learning-kit/pull/86) [`2215060`](https://github.com/intellectif/learning-kit/commit/22150600b0d8f5f058214a0551566b58e154276d) Thanks [@diego28e](https://github.com/diego28e)! - **Coaching on a reading aloud**: "Coach me on this reading" under a read-aloud's marks, where a model may coach only the words the speech engine marked.
8
+
9
+ **Action required:** none unless your code switches over `AiFeature`, `AiRefusal` or `InteractionKind` without a `default` branch (new members `'pronunciation-coaching'`, `'contradicts-marks'` and `'ai-coaching-shown'`), reads `AiCheckCase.request` without narrowing on `feature`, or implements a complete `LkStrings` (six new keys). Nothing changes until you pass a `pronunciationCoaching` port. Install lk-core 1.1.0 with lk-react 23.1.0: lk-react calls the new lk-core functions, and its peer range moves to `^1.1.0`. See https://github.com/intellectif/learning-kit/blob/main/docs/upgrading.md
10
+
11
+ - **lk-core:** `aiCoachingRequest` builds what a model is given: the text, the engine's marks word by word — with each word's sounds and what each was heard as, when the marks come from the assessment — its dimension scores, and the grade. `checkAiCoaching` checks the reply before a learner sees it. Every word it coaches must be one the engine marked mispronounced or omitted, and every sound one the engine reported for that word; anything else refuses the whole reply as `contradicts-marks`. The words come back in reading order, each as the marks show it, and no number in the reply is read. An assessment the grader would not read (no speech, unscripted, another text or locale) gives no coaching.
12
+ - **lk-react:** a `pronunciationCoaching` port on `LearnerAi`. `<ReadAloud>` offers coaching under its marks in `practice` once a take is graded and in `review` wherever marks are shown, from a kept assessment or a stored grade; never in `exam`. `<PronunciationFeedback>` offers it too, given the item's `id` and `title` in `data`, and takes `ai`, `renderMode`, `delivery` and `onInteraction` for it. It follows the author's and the paper's `ai.explanations` and needs `feedback`, not `solutions`. One coaching per take. `useAiCoaching` gives marks you draw yourself the same rules.
13
+ - **Records:** `ai-coaching-shown` (how many words were coached, provenance and usage; never the text), and `ai-help-refused` with `feature: 'pronunciation-coaching'`.
14
+ - **ai-check:** a `pronunciationCoaching` port runs four reading cases: a mispronounced "th" and a word left out, a clean reading, the same slips from a stored grade without sounds, and coaching asked for in Spanish.
15
+ - Six new strings: `aiCoaching`, `aiCoachingLoading`, `aiCoachingHeading`, `aiCoachingUnavailable`, `aiCoachingWords`, `aiCoachingSound`.
16
+ - **Stability:** the promise now says what a minor may add to a type the SDK hands you — a union member, a `LkStrings` key, an optional property — and that a `default` branch keeps a switch correct across minors.
17
+
18
+ ## 1.0.0
19
+
20
+ ### Major Changes
21
+
22
+ - [#82](https://github.com/intellectif/learning-kit/pull/82) [`bcae525`](https://github.com/intellectif/learning-kit/commit/bcae52599d7d0481ccd8ceecdfc59f2bd6d4d281) Thanks [@diego28e](https://github.com/diego28e)! - **1.0**: what every 1.x keeps stable, written down, and from now on a lk-core minor releases no lk-react. No grade changes.
23
+
24
+ **Action required:** only if you read `ScoringDetail.correct`, import a zod schema from lk-core, or register an activity type of your own. Install lk-core 1.0.0 and lk-react 23.0.0 together. Each change and its replacement is in the upgrading guide: https://github.com/intellectif/learning-kit/blob/main/docs/upgrading.md
25
+
26
+ - **Stability:** grades, the public API, content and runtimes — what a 1.x release may and may not change — are set out in https://github.com/intellectif/learning-kit/blob/main/docs/stability.md. lk-react 23 peers on `@intellectif/lk-core@^1.0.0`, and a lk-core minor or patch releases no lk-react.
27
+ - **`ScoringDetail.correct` is removed, and `outcome` is required.** Deprecated since 0.3; on a multiple-choice option it meant "the learner acted rightly on it". Read `outcome`. The grade-stability corpus changed only there: 142 vectors lose `correct`, and no score, pass or feedback moves. A detail stored before 0.3 still carries only `correct`; the SDK's components still read it.
28
+ - **Zod is private to lk-core.** No zod schema is exported and no published type names zod, so your app can use any zod, or none. `validateMedia` and `validateOptionMedia` replace `MediaSchema.safeParse` and `MultipleChoiceOptionMediaSchema.safeParse`; `validateActivity`, `validateDraft` and `validateItemGroup` replace the rest. The `*JsonSchema` constants are typed `Record<string, unknown>`, and the `Redacted*` types are written out, unchanged in shape.
29
+ - **A type you register takes Standard Schemas** (https://standardschema.dev): `schema` and `redactedSchema` are `StandardSchemaV1`. A zod 4 schema is one as written; valibot and ArkType work too. Validation must be synchronous. `registerActivityType` throws on a value that is not a Standard Schema, and `jsonSchemaFor` on your type needs the descriptor's new `jsonSchema` unless the schema produces JSON Schema itself, as zod 4.6 does.
30
+ - **Built on zod 4.6.5, pinned exactly**, instead of the zod 4 preview in zod 3.25. A new zod reaches you only in a lk-core release. If your app uses another version of zod, your bundle carries two copies. Every built-in validation accepts and refuses what it did, checked against 0.21.0 on 28,000 inputs; from 1.0, `vectors/validation.json` in the tarball freezes that for over three thousand inputs, and each release replays it. Two error lists are one error shorter: a speech assessment with a string where a list of phonemes or syllables belongs, and an xAPI statement whose actor's `mbox` is not a `mailto:` address.
31
+ - **Fixed (lk-react):** a host's grade whose details carry no `correct` — every detail lk-core 1.0 writes — had all its details dropped, a read-aloud's word marks among them. It is now read.
32
+
3
33
  ## 0.22.0
4
34
 
5
35
  ### Minor Changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @intellectif/lk-core
2
2
 
3
- Framework-free TypeScript core of [learning-kit](https://github.com/intellectif/learning-kit): Zod-based **activity schemas**, a pure **scoring engine**, **rubric and deferred grading**, **weighted assessment composition**, reproducible **exam attempt plans**, fail-closed **redaction**, and an **xAPI 1.0.3 statement builder + validator**. Zero React, zero DOM — usable in Node, browsers, edge, workers, or as the data layer behind `@intellectif/lk-react`.
3
+ Framework-free TypeScript core of [learning-kit](https://github.com/intellectif/learning-kit): **activity schemas and validation**, a pure **scoring engine**, **rubric and deferred grading**, **weighted assessment composition**, reproducible **exam attempt plans**, fail-closed **redaction**, and an **xAPI 1.0.3 statement builder + validator**. Zero React, zero DOM — usable in Node, browsers, edge, workers, or as the data layer behind `@intellectif/lk-react`.
4
4
 
5
5
  It is built for **summative** assessment as much as practice: nothing here grades on the client, "not marked yet" is a first-class outcome that is never conflated with a zero, and every behavioural change that could move a historical grade is opt-in. A frozen corpus of grading vectors ships in the package, fails CI if any of them moves, and can be replayed against the build you install.
6
6
 
@@ -28,7 +28,7 @@ npm install @intellectif/lk-core
28
28
  - **Item groups** — `Stimulus` + `ItemGroup` (one passage or recording serving several questions), `flattenSequence()` for seeded, shuffle-atomic presentation order with stable slot identity. Slot ids are positional by default (`"3"`, `"1.0"`); author a `slotKey` on an entry and its id survives an insert, so a stored response cannot slide onto a different question.
29
29
  - **Delivery policies** — `DeliveryPolicy` says what a school lets a learner see around a question: feedback, solutions, hints and AI help. `resolveDeliveryPolicy` spells one out (an unreadable setting restricts, never allows), `validateDeliveryPolicy` checks one before it is stored, and `combineDeliveryPolicies` keeps a setting on only where every policy leaves it on.
30
30
  - **Scoring policies** — `ItemScoringPolicy` says how a paper's questions are scored when a learner can try again or ask for hints: `retries`, which try `counts`, and what a try and a hint cost. `scoreTries` does the arithmetic, `evaluate(…, { scoring })` and `evaluateTries` reach a question's outcome from its answers, and `validateItemScoringPolicy` / `resolveItemScoringPolicy` refuse a policy that cannot be applied rather than guess — every setting moves a grade. No policy changes nothing, and the arithmetic is pinned by the grade vectors.
31
- - **AI help contracts** — the SDK calls no model; it builds what yours is given and checks what comes back. `aiExplanationRequest`, `aiHintRequest` and `aiWritingFeedbackRequest` build the requests a component makes, so a server can rebuild them from its own copy of an item; `checkAiExplanation`, `checkAiHint` and `checkAiWritingFeedback` refuse an explanation that contradicts the grade, a hint that contains the answer, and writing feedback that corrects words the learner never wrote, and `checkAiWritingFeedback` computes the rubric's indicative score itself.
31
+ - **AI help contracts** — the SDK calls no model; it builds what yours is given and checks what comes back. `aiExplanationRequest`, `aiHintRequest`, `aiWritingFeedbackRequest` and `aiCoachingRequest` build the requests a component makes, so a server can rebuild them from its own copy of an item; `checkAiExplanation`, `checkAiHint`, `checkAiWritingFeedback` and `checkAiCoaching` refuse an explanation that contradicts the grade, a hint that contains the answer, writing feedback that corrects words the learner never wrote, and coaching on a reading that names a word the speech engine did not mark or a sound it did not report; `checkAiWritingFeedback` computes the rubric's indicative score itself.
32
32
  - **Attempt plans** — `planAttempt(entries, { seed, shuffleEntries, points, delivery })` freezes the exact paper a learner sat, and the delivery policy it was sat under: slot order, per-slot points, a content hash of each item, and a `planHash` over the lot. `verifyAttemptPlan(plan, current)` reports the drift when that content is later edited (`changedSlotIds`, `changedStimulusSlotIds`, `changedPointsSlotIds`, `missingSlotIds`, …) — the thing you need during a remark or an appeal. `scoredItemsFromPlan(plan, outcomes)` turns collected outcomes into the `ScoredItem[]` composition wants, and defaults a slot with **no** outcome to `deferred` rather than silently shrinking the denominator.
33
33
  - **Attempt state** — `serializeAttemptState(plan, progress)` / `restoreAttemptState(plan, snapshot)` round-trip an interrupted attempt (responses, submitted slots, position) and are **bound to the plan**: restoring answers onto a paper the learner never sat throws instead of succeeding quietly. `diffResponses(before, after)` reports what moved between two snapshots, including an answer the learner *cleared*.
34
34
  - **Media playback policy** — `media.playback` on an audio recording: `maxPlays`, `seek`, `rate`, and advisory `nativeControlHints`. `resolvePlaybackPolicy()` derives the defaults once so the schema, the plan and the renderer cannot drift. Budgets are frozen into the plan by `planAttempt`, so editing `maxPlays` mid-window cannot change what a past learner was held to, and `planAttempt` refuses a paper where one recording is budgeted under two keys.
@@ -41,7 +41,7 @@ npm install @intellectif/lk-core
41
41
  - **xAPI builder** — `xAPIBuilder.buildAnsweredStatement(...)` / `buildSubmittedStatement(...)` / `buildCompletedStatement(...)` (plus `buildStatement(...)` for any verb) emit well-formed xAPI 1.0.3 statements with a v4 statement id and an ISO-8601 timestamp. Ids use `crypto.randomUUID()` where available and fall back to `crypto.getRandomValues()`, so statements stay well-formed on the non-secure origins `randomUUID` is gated behind.
42
42
  - **xAPI verbs for async grading** — `XAPIVerb.SUBMITTED` is emitted for work whose grade does not exist yet (`answered` would assert a score nobody computed), and `XAPIVerb.SCORED` is there for the grade that arrives later, often from a different actor. `XAPI_VERB_DISPLAY` supplies the `en-US` labels.
43
43
  - **`xapiDefinitionFor(data)`** — the xAPI interop descriptor (activity-type IRI, `cmi.interaction` type, `correctResponsesPattern`) for any registered type, so a consumer-registered activity gets correct interop with no component changes. Returns `{}` for an unregistered type, so it is always safe to spread.
44
- - **xAPI validator** — `validateXAPIStatement(statement)` (Zod-backed; throws on an invalid statement in development, warns in production).
44
+ - **xAPI validator** — `validateXAPIStatement(statement)` (throws on an invalid statement in development, warns in production).
45
45
  - **Errors** — `ActivitySchemaError`, `UnknownActivityTypeError`, `DeferredScoringError` and `RedactedScoringError`, all with structured payloads.
46
46
  - **Types** — `ActivityData`, `ActivityResult`, `ScoringResult`, `XAPIStatement`, `ThemeTokens`, … all exported with JSDoc.
47
47
 
@@ -115,7 +115,7 @@ result.passed; // boolean, or null while provisional. Never record a provision
115
115
  | Import | Contents |
116
116
  |---|---|
117
117
  | `@intellectif/lk-core` | Everything (barrel) |
118
- | `@intellectif/lk-core/schemas` | Zod schemas + `validateActivity` + JSON Schema export |
118
+ | `@intellectif/lk-core/schemas` | `validateActivity`, `validateItemGroup`, `validateMedia`, `validateOptionMedia`, `jsonSchemaFor` and the JSON Schemas, and the redacted types |
119
119
  | `@intellectif/lk-core/scoring` | `score`, `evaluate`, `composeAssessmentScore`, rounding, text matching |
120
120
  | `@intellectif/lk-core/xapi` | `xAPIBuilder`, `XAPIVerb`, `validateXAPIStatement` |
121
121
  | `@intellectif/lk-core/ai-check` | `runAiCheck`, `aiCheckCases`, `formatAiCheckReport` — test your AI prompts in CI |
@@ -124,8 +124,8 @@ The barrel re-exports everything, and it is the **only** entry point for attempt
124
124
  plans, attempt state, item groups, redaction, the type registry, authoring drafts
125
125
  and content hashing — those have no subpath of their own.
126
126
 
127
- All exports ship as ESM + CJS with `.d.ts` types. Tree-shakeable; `sideEffects: false`. Node >= 20. In browsers, the SDK's own code needs `Object.hasOwn` — Chrome and Edge 93, Firefox 92, Safari 15.4 — because output targets ES2022 and nothing is polyfilled.
128
- Zod is the single runtime dependency: the package depends on `zod@^3.25` and imports the **Zod 4 API** from its `zod/v4` subpath, so it coexists with an app still on Zod 3.
127
+ All exports ship as ESM + CJS with `.d.ts` types. Tree-shakeable; `sideEffects: false`. Node 22 or later. In browsers, the SDK's own code needs `Object.hasOwn` — Chrome and Edge 93, Firefox 92, Safari 15.4 — because output targets ES2022 and nothing is polyfilled.
128
+ Zod is the single runtime dependency, pinned to one exact version and private: no export is a zod schema and no published type names zod, so your app can use any version of zod, or none. The pin keeps validation to what the SDK tested — a new zod ships in a lk-core release, once the validation corpus replays unchanged — at the cost of a second copy of zod in a bundle whose own zod is another version. A type you register brings its own schema, from any library that implements [Standard Schema](https://standardschema.dev). What 1.x keeps stable is set out in [Stability](https://github.com/intellectif/learning-kit/blob/main/docs/stability.md).
129
129
 
130
130
  ## Releases & upgrading
131
131
 
@@ -226,8 +226,8 @@ interface GradeRecord {
226
226
  interface ActivityAiPermissions {
227
227
  /**
228
228
  * An explanation of the learner's graded answer — and, on a written
229
- * response, feedback on a draft: both are a model's words about the
230
- * learner's own answer.
229
+ * response, feedback on a draft, and on a read-aloud, coaching on the
230
+ * marks: each is a model's words about the learner's own answer.
231
231
  */
232
232
  explanations?: boolean;
233
233
  /** Hints before the learner submits. */
@@ -248,7 +248,7 @@ interface AiActivityInput {
248
248
  readonly ai?: unknown;
249
249
  }
250
250
  /** The kinds of help a learner can be given. */
251
- type AiFeature = 'explanation' | 'hint' | 'writing-feedback';
251
+ type AiFeature = 'explanation' | 'hint' | 'writing-feedback' | 'pronunciation-coaching';
252
252
  /** The activity types the SDK builds facts for. */
253
253
  type AiSupportedActivityType = 'multiple-choice' | 'fill-in-the-blanks' | 'gap-select' | 'dictation';
254
254
  /**
@@ -411,9 +411,10 @@ interface AiTextResult {
411
411
  /**
412
412
  * Why a result was not shown. `misquotes-answer` is writing feedback that
413
413
  * corrects words the learner did not write: a correction whose quote is not in
414
- * the draft, or not where it claims to be.
414
+ * the draft, or not where it claims to be. `contradicts-marks` is coaching on
415
+ * a word the engine did not mark, or on a sound it did not report.
415
416
  */
416
- type AiRefusal = 'malformed' | 'empty' | 'too-long' | 'contradicts-grade' | 'reveals-answer' | 'misquotes-answer';
417
+ type AiRefusal = 'malformed' | 'empty' | 'too-long' | 'contradicts-grade' | 'reveals-answer' | 'misquotes-answer' | 'contradicts-marks';
417
418
  /** One criterion of a written response's rubric, as the author wrote it. */
418
419
  interface AiRubricCriterionFact {
419
420
  name: string;
@@ -519,6 +520,110 @@ interface AiWritingFeedback {
519
520
  provenance?: AiProvenance;
520
521
  usage?: GraderUsage;
521
522
  }
523
+ /** One sound of a word, as the engine reported it. */
524
+ interface AiSoundFact {
525
+ /** The sound expected, in the assessment's phoneme alphabet. */
526
+ symbol: string;
527
+ /** How close it came, 0..100, when the engine scored it. */
528
+ accuracy?: number;
529
+ /** What the engine heard instead, best first, each with its score 0..100. */
530
+ heardAs?: {
531
+ symbol: string;
532
+ score: number;
533
+ }[];
534
+ }
535
+ /** One word of a reading, as the engine marked it. */
536
+ interface AiReadingWordFact {
537
+ /** `w<n>` for a word of the text; absent for a word the learner added. */
538
+ itemId?: string;
539
+ /** The word of the text, normalised; `''` for a word the learner added. */
540
+ word: string;
541
+ /** What was heard, normalised; `''` for an omitted word. */
542
+ heard: string;
543
+ state: 'correct' | 'mispronounced' | 'omitted' | 'inserted';
544
+ /** The engine's accuracy for the word, 0..100, when it has one. */
545
+ accuracy?: number;
546
+ /** The word's sounds, from the full assessment only. */
547
+ sounds?: AiSoundFact[];
548
+ }
549
+ /**
550
+ * What a model is told about a read-aloud: the text, the engine's marks word
551
+ * by word, and its scores. The marks are the engine's; a model explains them
552
+ * and never makes its own.
553
+ */
554
+ interface AiReadingFacts {
555
+ activityType: 'read-aloud';
556
+ activityId: string;
557
+ title: string;
558
+ /** The language the text is in. */
559
+ locale: string;
560
+ referenceText: string;
561
+ instructions?: string;
562
+ /** Who made the marks: a measurement engine, a model, or a person. */
563
+ assessor: 'auto' | 'ai' | 'human' | 'unknown';
564
+ /** The alphabet `sounds` are written in, when any are. */
565
+ phonemeAlphabet?: 'ipa' | 'sapi';
566
+ /** The engine's dimension scores, each 0..100, where it measured them. */
567
+ scores: {
568
+ accuracy?: number;
569
+ fluency?: number;
570
+ completeness?: number;
571
+ prosody?: number;
572
+ };
573
+ words: AiReadingWordFact[];
574
+ }
575
+ /**
576
+ * Asks for coaching on a graded reading: what to work on, word by word, and
577
+ * how. Never in an exam.
578
+ */
579
+ interface AiCoachingRequest {
580
+ feature: 'pronunciation-coaching';
581
+ facts: AiReadingFacts;
582
+ /** The grade of the reading, when there is one. */
583
+ grade?: {
584
+ score: number;
585
+ maxScore: number;
586
+ passed: boolean;
587
+ };
588
+ /** The language to write in: the learner's interface language, when known. */
589
+ learnerLocale?: string;
590
+ }
591
+ /** One word a model coaches, as it returns it. */
592
+ interface AiCoachingWord {
593
+ /** The `itemId` of a word the engine marked mispronounced or omitted. */
594
+ itemId: string;
595
+ /** What to do about it, addressed to the learner. */
596
+ tip: string;
597
+ /**
598
+ * A sound the engine reported for this word — `expected` — and, if the
599
+ * model names one, what the engine heard instead.
600
+ */
601
+ sound?: {
602
+ expected: string;
603
+ heard?: string;
604
+ };
605
+ }
606
+ /** What a host's `pronunciationCoaching` port returns. */
607
+ interface AiCoachingResult {
608
+ /** The coaching as a whole, addressed to the learner. Plain text, never HTML. */
609
+ text: string;
610
+ words?: AiCoachingWord[];
611
+ provenance?: AiProvenance;
612
+ usage?: GraderUsage;
613
+ }
614
+ /** Coaching, as the SDK accepted it: what a learner is shown. */
615
+ interface AiCoaching {
616
+ text: string;
617
+ /**
618
+ * The words to work on, in reading order, each with the word of the text as
619
+ * the SDK has it — never the model's spelling of it.
620
+ */
621
+ words: (AiCoachingWord & {
622
+ word: string;
623
+ })[];
624
+ provenance?: AiProvenance;
625
+ usage?: GraderUsage;
626
+ }
522
627
 
523
628
  /**
524
629
  * An xAPI Activity object — the thing a statement is about.
@@ -1460,8 +1565,7 @@ interface ReadAloudLearnerResponse {
1460
1565
  takes?: number;
1461
1566
  }
1462
1567
  /**
1463
- * Fine-grained outcome of the learner's action on a single item, replacing the
1464
- * ambiguous {@link ScoringDetail.correct}:
1568
+ * Fine-grained outcome of the learner's action on a single item:
1465
1569
  * - `correct` — the learner selected/entered the right answer.
1466
1570
  * - `incorrect` — the learner selected/entered a wrong answer.
1467
1571
  * - `correct-omission` — the learner correctly left a non-answer unselected (multiple-choice only).
@@ -1474,20 +1578,17 @@ interface ScoringDetail {
1474
1578
  /** ID of the option, blank, gap or dictation word (`w1`…`wN`) this detail refers to. */
1475
1579
  itemId: string;
1476
1580
  /**
1477
- * @deprecated Ambiguous: for multiple-choice this means "the learner acted
1478
- * correctly on this option" (`wasSelected === option.isCorrect`), NOT "this
1479
- * option is the answer" — an unselected wrong option reads `correct: true`.
1480
- * Read {@link ScoringDetail.outcome} instead; `correct` remains written for
1481
- * backward compatibility and will be removed in v1.0.
1482
- */
1483
- correct: boolean;
1484
- /**
1485
- * Unambiguous outcome of the learner's action on this item. Optional in the
1486
- * type so 0.2-era consumer-constructed literals keep compiling, but ALWAYS
1487
- * written by every built-in scorer (by the first two since 0.3.0); becomes
1488
- * required in v1.0 when the deprecated `correct` is removed.
1581
+ * The outcome of the learner's action on this item. On a multiple-choice
1582
+ * option it says both whether the option was chosen and whether it is part
1583
+ * of the answer.
1584
+ *
1585
+ * Until 1.0 a detail also carried `correct`, which on a multiple-choice
1586
+ * option meant "the learner acted correctly on it" — an unselected wrong
1587
+ * option read `correct: true` — and a detail stored before 0.3 carries only
1588
+ * that. The SDK's components still read such a stored detail; a type written
1589
+ * against 1.0 does not describe it.
1489
1590
  */
1490
- outcome?: ScoringOutcome;
1591
+ outcome: ScoringOutcome;
1491
1592
  /** The learner's actual response for this item. */
1492
1593
  learnerResponse: string | string[];
1493
1594
  /** The expected correct response(s) for this item. */
@@ -1718,7 +1819,12 @@ type InteractionKind = 'option-selected' | 'option-deselected' | 'blank-filled'
1718
1819
  * number of `corrections`, the `indicativeScore` when there was one, and the
1719
1820
  * port's `provenance` and `usage` when it sent them). Never the text.
1720
1821
  */
1721
- | 'ai-writing-feedback-shown' | (string & {});
1822
+ | 'ai-writing-feedback-shown'
1823
+ /**
1824
+ * Coaching on a read-aloud was shown (the number of `words` it coached, and
1825
+ * the port's `provenance` and `usage` when it sent them). Never the text.
1826
+ */
1827
+ | 'ai-coaching-shown' | (string & {});
1722
1828
  /** Fired by activity components on every discrete learner interaction. */
1723
1829
  interface InteractionEvent {
1724
1830
  /** The kind of interaction that occurred. */
@@ -1731,4 +1837,4 @@ interface InteractionEvent {
1731
1837
  payload: Record<string, unknown>;
1732
1838
  }
1733
1839
 
1734
- export { type GradingState as $, type ActivityAiPermissions as A, type AiWordFact as B, type AiWritingCorrection as C, type AiWritingFacts as D, type AiWritingFeedback as E, type AiWritingFeedbackRequest as F, type AiWritingFeedbackResult as G, type BlankConfig as H, type CriterionScore as I, type DeferredReason as J, type DeferredScoringPartial as K, type DictationData as L, type DictationEquivalence as M, type DictationLearnerResponse as N, type DictationSlowMedia as O, type DictationTolerance as P, type FillInTheBlanksData as Q, type FillInTheBlanksLearnerResponse as R, type GapSelectBank as S, type GapSelectChoice as T, type GapSelectData as U, type GapSelectGap as V, type GapSelectLearnerResponse as W, type GradeRecord as X, type Grader as Y, type GraderKind as Z, type GraderUsage as _, type ActivityData as a, type InlineCorrection as a0, type InteractionEvent as a1, type InteractionKind as a2, type ItemOutcome as a3, type LearnerResponse as a4, type LearnerResponseMap as a5, type MediaPlaybackPolicy as a6, type MediaTrack as a7, type MultipleChoiceData as a8, type MultipleChoiceLearnerResponse as a9, type XAPIObject as aA, type XAPIResult as aB, type XAPIScore as aC, type XAPIStatement as aD, type XAPIVerbObject as aE, levenshteinDistance as aF, matchText as aG, type MultipleChoiceOption as aa, type MultipleChoiceOptionMedia as ab, type NativeControlHint as ac, type ReadAloudData as ad, type ReadAloudDimension as ae, type ReadAloudDimensionWeight as af, type ReadAloudLearnerResponse as ag, type ReadAloudSlowMedia as ah, type RecordingBounds as ai, type RecordingRef as aj, type ScoringDetail as ak, type ScoringOutcome as al, type ScoringResult as am, type TextMatchPolicy as an, type TextMatchResult as ao, type ValidationError as ap, type ValidationResult as aq, type WrittenResponseData as ar, type WrittenResponseLearnerResponse as as, type WrittenResponseRubric as at, type WrittenResponseRubricCriterion as au, type XAPIActor as av, type XAPIConfig as aw, type XAPIContext as ax, type XAPIContextActivities as ay, type XAPIError as az, type ActivityDataMap as b, type ActivityFeedback as c, type ActivityMedia as d, type ActivityResult as e, type ActivityType as f, type AiActivityInput as g, type AiBlankFact as h, type AiCriterionJudgement as i, type AiDictationFacts as j, type AiExplanationRequest as k, type AiFeature as l, type AiFillInTheBlanksFacts as m, type AiGapFact as n, type AiGapSelectFacts as o, type AiGrade as p, type AiHintRequest as q, type AiItemFacts as r, type AiMultipleChoiceFacts as s, type AiOptionFact as t, type AiProvenance as u, type AiRefusal as v, type AiRubricCriterionFact as w, type AiSupportedActivityType as x, type AiTextResult as y, type AiVerdict as z };
1840
+ export { type GapSelectData as $, type ActivityAiPermissions as A, type AiReadingWordFact as B, type AiRefusal as C, type AiRubricCriterionFact as D, type AiSoundFact as E, type AiSupportedActivityType as F, type AiTextResult as G, type AiVerdict as H, type AiWordFact as I, type AiWritingCorrection as J, type AiWritingFacts as K, type AiWritingFeedback as L, type AiWritingFeedbackRequest as M, type AiWritingFeedbackResult as N, type BlankConfig as O, type CriterionScore as P, type DeferredReason as Q, type DeferredScoringPartial as R, type DictationData as S, type DictationEquivalence as T, type DictationLearnerResponse as U, type DictationSlowMedia as V, type DictationTolerance as W, type FillInTheBlanksData as X, type FillInTheBlanksLearnerResponse as Y, type GapSelectBank as Z, type GapSelectChoice as _, type ActivityData as a, type GapSelectGap as a0, type GapSelectLearnerResponse as a1, type GradeRecord as a2, type Grader as a3, type GraderKind as a4, type GraderUsage as a5, type GradingState as a6, type InlineCorrection as a7, type InteractionEvent as a8, type InteractionKind as a9, type WrittenResponseRubric as aA, type WrittenResponseRubricCriterion as aB, type XAPIActor as aC, type XAPIConfig as aD, type XAPIContext as aE, type XAPIContextActivities as aF, type XAPIError as aG, type XAPIObject as aH, type XAPIResult as aI, type XAPIScore as aJ, type XAPIStatement as aK, type XAPIVerbObject as aL, levenshteinDistance as aM, matchText as aN, type ItemOutcome as aa, type LearnerResponse as ab, type LearnerResponseMap as ac, type MediaPlaybackPolicy as ad, type MediaTrack as ae, type MultipleChoiceData as af, type MultipleChoiceLearnerResponse as ag, type MultipleChoiceOption as ah, type MultipleChoiceOptionMedia as ai, type NativeControlHint as aj, type ReadAloudData as ak, type ReadAloudDimension as al, type ReadAloudDimensionWeight as am, type ReadAloudLearnerResponse as an, type ReadAloudSlowMedia as ao, type RecordingBounds as ap, type RecordingRef as aq, type ScoringDetail as ar, type ScoringOutcome as as, type ScoringResult as at, type TextMatchPolicy as au, type TextMatchResult as av, type ValidationError as aw, type ValidationResult as ax, type WrittenResponseData as ay, type WrittenResponseLearnerResponse as az, type ActivityDataMap as b, type ActivityFeedback as c, type ActivityMedia as d, type ActivityResult as e, type ActivityType as f, type AiActivityInput as g, type AiBlankFact as h, type AiCoaching as i, type AiCoachingRequest as j, type AiCoachingResult as k, type AiCoachingWord as l, type AiCriterionJudgement as m, type AiDictationFacts as n, type AiExplanationRequest as o, type AiFeature as p, type AiFillInTheBlanksFacts as q, type AiGapFact as r, type AiGapSelectFacts as s, type AiGrade as t, type AiHintRequest as u, type AiItemFacts as v, type AiMultipleChoiceFacts as w, type AiOptionFact as x, type AiProvenance as y, type AiReadingFacts as z };
@@ -226,8 +226,8 @@ interface GradeRecord {
226
226
  interface ActivityAiPermissions {
227
227
  /**
228
228
  * An explanation of the learner's graded answer — and, on a written
229
- * response, feedback on a draft: both are a model's words about the
230
- * learner's own answer.
229
+ * response, feedback on a draft, and on a read-aloud, coaching on the
230
+ * marks: each is a model's words about the learner's own answer.
231
231
  */
232
232
  explanations?: boolean;
233
233
  /** Hints before the learner submits. */
@@ -248,7 +248,7 @@ interface AiActivityInput {
248
248
  readonly ai?: unknown;
249
249
  }
250
250
  /** The kinds of help a learner can be given. */
251
- type AiFeature = 'explanation' | 'hint' | 'writing-feedback';
251
+ type AiFeature = 'explanation' | 'hint' | 'writing-feedback' | 'pronunciation-coaching';
252
252
  /** The activity types the SDK builds facts for. */
253
253
  type AiSupportedActivityType = 'multiple-choice' | 'fill-in-the-blanks' | 'gap-select' | 'dictation';
254
254
  /**
@@ -411,9 +411,10 @@ interface AiTextResult {
411
411
  /**
412
412
  * Why a result was not shown. `misquotes-answer` is writing feedback that
413
413
  * corrects words the learner did not write: a correction whose quote is not in
414
- * the draft, or not where it claims to be.
414
+ * the draft, or not where it claims to be. `contradicts-marks` is coaching on
415
+ * a word the engine did not mark, or on a sound it did not report.
415
416
  */
416
- type AiRefusal = 'malformed' | 'empty' | 'too-long' | 'contradicts-grade' | 'reveals-answer' | 'misquotes-answer';
417
+ type AiRefusal = 'malformed' | 'empty' | 'too-long' | 'contradicts-grade' | 'reveals-answer' | 'misquotes-answer' | 'contradicts-marks';
417
418
  /** One criterion of a written response's rubric, as the author wrote it. */
418
419
  interface AiRubricCriterionFact {
419
420
  name: string;
@@ -519,6 +520,110 @@ interface AiWritingFeedback {
519
520
  provenance?: AiProvenance;
520
521
  usage?: GraderUsage;
521
522
  }
523
+ /** One sound of a word, as the engine reported it. */
524
+ interface AiSoundFact {
525
+ /** The sound expected, in the assessment's phoneme alphabet. */
526
+ symbol: string;
527
+ /** How close it came, 0..100, when the engine scored it. */
528
+ accuracy?: number;
529
+ /** What the engine heard instead, best first, each with its score 0..100. */
530
+ heardAs?: {
531
+ symbol: string;
532
+ score: number;
533
+ }[];
534
+ }
535
+ /** One word of a reading, as the engine marked it. */
536
+ interface AiReadingWordFact {
537
+ /** `w<n>` for a word of the text; absent for a word the learner added. */
538
+ itemId?: string;
539
+ /** The word of the text, normalised; `''` for a word the learner added. */
540
+ word: string;
541
+ /** What was heard, normalised; `''` for an omitted word. */
542
+ heard: string;
543
+ state: 'correct' | 'mispronounced' | 'omitted' | 'inserted';
544
+ /** The engine's accuracy for the word, 0..100, when it has one. */
545
+ accuracy?: number;
546
+ /** The word's sounds, from the full assessment only. */
547
+ sounds?: AiSoundFact[];
548
+ }
549
+ /**
550
+ * What a model is told about a read-aloud: the text, the engine's marks word
551
+ * by word, and its scores. The marks are the engine's; a model explains them
552
+ * and never makes its own.
553
+ */
554
+ interface AiReadingFacts {
555
+ activityType: 'read-aloud';
556
+ activityId: string;
557
+ title: string;
558
+ /** The language the text is in. */
559
+ locale: string;
560
+ referenceText: string;
561
+ instructions?: string;
562
+ /** Who made the marks: a measurement engine, a model, or a person. */
563
+ assessor: 'auto' | 'ai' | 'human' | 'unknown';
564
+ /** The alphabet `sounds` are written in, when any are. */
565
+ phonemeAlphabet?: 'ipa' | 'sapi';
566
+ /** The engine's dimension scores, each 0..100, where it measured them. */
567
+ scores: {
568
+ accuracy?: number;
569
+ fluency?: number;
570
+ completeness?: number;
571
+ prosody?: number;
572
+ };
573
+ words: AiReadingWordFact[];
574
+ }
575
+ /**
576
+ * Asks for coaching on a graded reading: what to work on, word by word, and
577
+ * how. Never in an exam.
578
+ */
579
+ interface AiCoachingRequest {
580
+ feature: 'pronunciation-coaching';
581
+ facts: AiReadingFacts;
582
+ /** The grade of the reading, when there is one. */
583
+ grade?: {
584
+ score: number;
585
+ maxScore: number;
586
+ passed: boolean;
587
+ };
588
+ /** The language to write in: the learner's interface language, when known. */
589
+ learnerLocale?: string;
590
+ }
591
+ /** One word a model coaches, as it returns it. */
592
+ interface AiCoachingWord {
593
+ /** The `itemId` of a word the engine marked mispronounced or omitted. */
594
+ itemId: string;
595
+ /** What to do about it, addressed to the learner. */
596
+ tip: string;
597
+ /**
598
+ * A sound the engine reported for this word — `expected` — and, if the
599
+ * model names one, what the engine heard instead.
600
+ */
601
+ sound?: {
602
+ expected: string;
603
+ heard?: string;
604
+ };
605
+ }
606
+ /** What a host's `pronunciationCoaching` port returns. */
607
+ interface AiCoachingResult {
608
+ /** The coaching as a whole, addressed to the learner. Plain text, never HTML. */
609
+ text: string;
610
+ words?: AiCoachingWord[];
611
+ provenance?: AiProvenance;
612
+ usage?: GraderUsage;
613
+ }
614
+ /** Coaching, as the SDK accepted it: what a learner is shown. */
615
+ interface AiCoaching {
616
+ text: string;
617
+ /**
618
+ * The words to work on, in reading order, each with the word of the text as
619
+ * the SDK has it — never the model's spelling of it.
620
+ */
621
+ words: (AiCoachingWord & {
622
+ word: string;
623
+ })[];
624
+ provenance?: AiProvenance;
625
+ usage?: GraderUsage;
626
+ }
522
627
 
523
628
  /**
524
629
  * An xAPI Activity object — the thing a statement is about.
@@ -1460,8 +1565,7 @@ interface ReadAloudLearnerResponse {
1460
1565
  takes?: number;
1461
1566
  }
1462
1567
  /**
1463
- * Fine-grained outcome of the learner's action on a single item, replacing the
1464
- * ambiguous {@link ScoringDetail.correct}:
1568
+ * Fine-grained outcome of the learner's action on a single item:
1465
1569
  * - `correct` — the learner selected/entered the right answer.
1466
1570
  * - `incorrect` — the learner selected/entered a wrong answer.
1467
1571
  * - `correct-omission` — the learner correctly left a non-answer unselected (multiple-choice only).
@@ -1474,20 +1578,17 @@ interface ScoringDetail {
1474
1578
  /** ID of the option, blank, gap or dictation word (`w1`…`wN`) this detail refers to. */
1475
1579
  itemId: string;
1476
1580
  /**
1477
- * @deprecated Ambiguous: for multiple-choice this means "the learner acted
1478
- * correctly on this option" (`wasSelected === option.isCorrect`), NOT "this
1479
- * option is the answer" — an unselected wrong option reads `correct: true`.
1480
- * Read {@link ScoringDetail.outcome} instead; `correct` remains written for
1481
- * backward compatibility and will be removed in v1.0.
1482
- */
1483
- correct: boolean;
1484
- /**
1485
- * Unambiguous outcome of the learner's action on this item. Optional in the
1486
- * type so 0.2-era consumer-constructed literals keep compiling, but ALWAYS
1487
- * written by every built-in scorer (by the first two since 0.3.0); becomes
1488
- * required in v1.0 when the deprecated `correct` is removed.
1581
+ * The outcome of the learner's action on this item. On a multiple-choice
1582
+ * option it says both whether the option was chosen and whether it is part
1583
+ * of the answer.
1584
+ *
1585
+ * Until 1.0 a detail also carried `correct`, which on a multiple-choice
1586
+ * option meant "the learner acted correctly on it" — an unselected wrong
1587
+ * option read `correct: true` — and a detail stored before 0.3 carries only
1588
+ * that. The SDK's components still read such a stored detail; a type written
1589
+ * against 1.0 does not describe it.
1489
1590
  */
1490
- outcome?: ScoringOutcome;
1591
+ outcome: ScoringOutcome;
1491
1592
  /** The learner's actual response for this item. */
1492
1593
  learnerResponse: string | string[];
1493
1594
  /** The expected correct response(s) for this item. */
@@ -1718,7 +1819,12 @@ type InteractionKind = 'option-selected' | 'option-deselected' | 'blank-filled'
1718
1819
  * number of `corrections`, the `indicativeScore` when there was one, and the
1719
1820
  * port's `provenance` and `usage` when it sent them). Never the text.
1720
1821
  */
1721
- | 'ai-writing-feedback-shown' | (string & {});
1822
+ | 'ai-writing-feedback-shown'
1823
+ /**
1824
+ * Coaching on a read-aloud was shown (the number of `words` it coached, and
1825
+ * the port's `provenance` and `usage` when it sent them). Never the text.
1826
+ */
1827
+ | 'ai-coaching-shown' | (string & {});
1722
1828
  /** Fired by activity components on every discrete learner interaction. */
1723
1829
  interface InteractionEvent {
1724
1830
  /** The kind of interaction that occurred. */
@@ -1731,4 +1837,4 @@ interface InteractionEvent {
1731
1837
  payload: Record<string, unknown>;
1732
1838
  }
1733
1839
 
1734
- export { type GradingState as $, type ActivityAiPermissions as A, type AiWordFact as B, type AiWritingCorrection as C, type AiWritingFacts as D, type AiWritingFeedback as E, type AiWritingFeedbackRequest as F, type AiWritingFeedbackResult as G, type BlankConfig as H, type CriterionScore as I, type DeferredReason as J, type DeferredScoringPartial as K, type DictationData as L, type DictationEquivalence as M, type DictationLearnerResponse as N, type DictationSlowMedia as O, type DictationTolerance as P, type FillInTheBlanksData as Q, type FillInTheBlanksLearnerResponse as R, type GapSelectBank as S, type GapSelectChoice as T, type GapSelectData as U, type GapSelectGap as V, type GapSelectLearnerResponse as W, type GradeRecord as X, type Grader as Y, type GraderKind as Z, type GraderUsage as _, type ActivityData as a, type InlineCorrection as a0, type InteractionEvent as a1, type InteractionKind as a2, type ItemOutcome as a3, type LearnerResponse as a4, type LearnerResponseMap as a5, type MediaPlaybackPolicy as a6, type MediaTrack as a7, type MultipleChoiceData as a8, type MultipleChoiceLearnerResponse as a9, type XAPIObject as aA, type XAPIResult as aB, type XAPIScore as aC, type XAPIStatement as aD, type XAPIVerbObject as aE, levenshteinDistance as aF, matchText as aG, type MultipleChoiceOption as aa, type MultipleChoiceOptionMedia as ab, type NativeControlHint as ac, type ReadAloudData as ad, type ReadAloudDimension as ae, type ReadAloudDimensionWeight as af, type ReadAloudLearnerResponse as ag, type ReadAloudSlowMedia as ah, type RecordingBounds as ai, type RecordingRef as aj, type ScoringDetail as ak, type ScoringOutcome as al, type ScoringResult as am, type TextMatchPolicy as an, type TextMatchResult as ao, type ValidationError as ap, type ValidationResult as aq, type WrittenResponseData as ar, type WrittenResponseLearnerResponse as as, type WrittenResponseRubric as at, type WrittenResponseRubricCriterion as au, type XAPIActor as av, type XAPIConfig as aw, type XAPIContext as ax, type XAPIContextActivities as ay, type XAPIError as az, type ActivityDataMap as b, type ActivityFeedback as c, type ActivityMedia as d, type ActivityResult as e, type ActivityType as f, type AiActivityInput as g, type AiBlankFact as h, type AiCriterionJudgement as i, type AiDictationFacts as j, type AiExplanationRequest as k, type AiFeature as l, type AiFillInTheBlanksFacts as m, type AiGapFact as n, type AiGapSelectFacts as o, type AiGrade as p, type AiHintRequest as q, type AiItemFacts as r, type AiMultipleChoiceFacts as s, type AiOptionFact as t, type AiProvenance as u, type AiRefusal as v, type AiRubricCriterionFact as w, type AiSupportedActivityType as x, type AiTextResult as y, type AiVerdict as z };
1840
+ export { type GapSelectData as $, type ActivityAiPermissions as A, type AiReadingWordFact as B, type AiRefusal as C, type AiRubricCriterionFact as D, type AiSoundFact as E, type AiSupportedActivityType as F, type AiTextResult as G, type AiVerdict as H, type AiWordFact as I, type AiWritingCorrection as J, type AiWritingFacts as K, type AiWritingFeedback as L, type AiWritingFeedbackRequest as M, type AiWritingFeedbackResult as N, type BlankConfig as O, type CriterionScore as P, type DeferredReason as Q, type DeferredScoringPartial as R, type DictationData as S, type DictationEquivalence as T, type DictationLearnerResponse as U, type DictationSlowMedia as V, type DictationTolerance as W, type FillInTheBlanksData as X, type FillInTheBlanksLearnerResponse as Y, type GapSelectBank as Z, type GapSelectChoice as _, type ActivityData as a, type GapSelectGap as a0, type GapSelectLearnerResponse as a1, type GradeRecord as a2, type Grader as a3, type GraderKind as a4, type GraderUsage as a5, type GradingState as a6, type InlineCorrection as a7, type InteractionEvent as a8, type InteractionKind as a9, type WrittenResponseRubric as aA, type WrittenResponseRubricCriterion as aB, type XAPIActor as aC, type XAPIConfig as aD, type XAPIContext as aE, type XAPIContextActivities as aF, type XAPIError as aG, type XAPIObject as aH, type XAPIResult as aI, type XAPIScore as aJ, type XAPIStatement as aK, type XAPIVerbObject as aL, levenshteinDistance as aM, matchText as aN, type ItemOutcome as aa, type LearnerResponse as ab, type LearnerResponseMap as ac, type MediaPlaybackPolicy as ad, type MediaTrack as ae, type MultipleChoiceData as af, type MultipleChoiceLearnerResponse as ag, type MultipleChoiceOption as ah, type MultipleChoiceOptionMedia as ai, type NativeControlHint as aj, type ReadAloudData as ak, type ReadAloudDimension as al, type ReadAloudDimensionWeight as am, type ReadAloudLearnerResponse as an, type ReadAloudSlowMedia as ao, type RecordingBounds as ap, type RecordingRef as aq, type ScoringDetail as ar, type ScoringOutcome as as, type ScoringResult as at, type TextMatchPolicy as au, type TextMatchResult as av, type ValidationError as aw, type ValidationResult as ax, type WrittenResponseData as ay, type WrittenResponseLearnerResponse as az, type ActivityDataMap as b, type ActivityFeedback as c, type ActivityMedia as d, type ActivityResult as e, type ActivityType as f, type AiActivityInput as g, type AiBlankFact as h, type AiCoaching as i, type AiCoachingRequest as j, type AiCoachingResult as k, type AiCoachingWord as l, type AiCriterionJudgement as m, type AiDictationFacts as n, type AiExplanationRequest as o, type AiFeature as p, type AiFillInTheBlanksFacts as q, type AiGapFact as r, type AiGapSelectFacts as s, type AiGrade as t, type AiHintRequest as u, type AiItemFacts as v, type AiMultipleChoiceFacts as w, type AiOptionFact as x, type AiProvenance as y, type AiReadingFacts as z };