@happyvertical/smrt-education 0.57.43 → 0.57.44

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 (82) hide show
  1. package/AGENTS.md +12 -0
  2. package/README.md +5 -0
  3. package/agents/course-authoring-service.md +179 -0
  4. package/agents/course-generation-review.md +79 -0
  5. package/agents/learner-service.md +33 -0
  6. package/agents/question-records.md +100 -0
  7. package/dist/chunks/{workbook-photo-service-C6mbUUp6.js → workbook-photo-service-BxvZDqjM.js} +1440 -309
  8. package/dist/chunks/workbook-photo-service-BxvZDqjM.js.map +1 -0
  9. package/dist/course-append-only.d.ts +15 -0
  10. package/dist/course-append-only.d.ts.map +1 -0
  11. package/dist/course-authoring-contracts.d.ts +464 -0
  12. package/dist/course-authoring-contracts.d.ts.map +1 -0
  13. package/dist/course-authoring-licence.d.ts +15 -0
  14. package/dist/course-authoring-licence.d.ts.map +1 -0
  15. package/dist/course-authoring-models.d.ts +291 -0
  16. package/dist/course-authoring-models.d.ts.map +1 -0
  17. package/dist/course-authoring-service.d.ts +244 -0
  18. package/dist/course-authoring-service.d.ts.map +1 -0
  19. package/dist/course-delegation.d.ts +26 -0
  20. package/dist/course-delegation.d.ts.map +1 -0
  21. package/dist/course-generation-contracts.d.ts +150 -0
  22. package/dist/course-generation-contracts.d.ts.map +1 -0
  23. package/dist/course-generation-models.d.ts +94 -0
  24. package/dist/course-generation-models.d.ts.map +1 -0
  25. package/dist/course-generation-output.d.ts +31 -0
  26. package/dist/course-generation-output.d.ts.map +1 -0
  27. package/dist/course-generation-proposal-generator.d.ts +94 -0
  28. package/dist/course-generation-proposal-generator.d.ts.map +1 -0
  29. package/dist/course-generation-review-service.d.ts +149 -0
  30. package/dist/course-generation-review-service.d.ts.map +1 -0
  31. package/dist/course-release-scope.d.ts +37 -0
  32. package/dist/course-release-scope.d.ts.map +1 -0
  33. package/dist/course-review-contracts.d.ts +127 -0
  34. package/dist/course-review-contracts.d.ts.map +1 -0
  35. package/dist/course-review-digest.d.ts +4 -0
  36. package/dist/course-review-digest.d.ts.map +1 -0
  37. package/dist/course-review-evaluation.d.ts +63 -0
  38. package/dist/course-review-evaluation.d.ts.map +1 -0
  39. package/dist/course-review-gate.d.ts +15 -0
  40. package/dist/course-review-gate.d.ts.map +1 -0
  41. package/dist/course-review-models.d.ts +96 -0
  42. package/dist/course-review-models.d.ts.map +1 -0
  43. package/dist/group-sharing-contracts.d.ts +5 -0
  44. package/dist/group-sharing-contracts.d.ts.map +1 -1
  45. package/dist/group-sharing-policy.d.ts.map +1 -1
  46. package/dist/group-sharing-reader.d.ts.map +1 -1
  47. package/dist/index.d.ts +27 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +5658 -116
  50. package/dist/index.js.map +1 -1
  51. package/dist/ingestion.js +1 -1
  52. package/dist/learner-plan-service.d.ts.map +1 -1
  53. package/dist/learner-service.d.ts +81 -7
  54. package/dist/learner-service.d.ts.map +1 -1
  55. package/dist/learners.d.ts +6 -0
  56. package/dist/learners.d.ts.map +1 -1
  57. package/dist/manifest.json +14304 -2177
  58. package/dist/question-authoring-service.d.ts +125 -0
  59. package/dist/question-authoring-service.d.ts.map +1 -0
  60. package/dist/question-content.d.ts +25 -0
  61. package/dist/question-content.d.ts.map +1 -0
  62. package/dist/question-contracts.d.ts +240 -0
  63. package/dist/question-contracts.d.ts.map +1 -0
  64. package/dist/question-models.d.ts +124 -0
  65. package/dist/question-models.d.ts.map +1 -0
  66. package/dist/question-render.d.ts +20 -0
  67. package/dist/question-render.d.ts.map +1 -0
  68. package/dist/question-response-contracts.d.ts +54 -0
  69. package/dist/question-response-contracts.d.ts.map +1 -0
  70. package/dist/question-response-service.d.ts +63 -0
  71. package/dist/question-response-service.d.ts.map +1 -0
  72. package/dist/question-rubric.d.ts +23 -0
  73. package/dist/question-rubric.d.ts.map +1 -0
  74. package/dist/smrt-knowledge.json +5410 -910
  75. package/dist/submission-service.d.ts.map +1 -1
  76. package/dist/submissions.d.ts +5 -0
  77. package/dist/submissions.d.ts.map +1 -1
  78. package/dist/workbook-contracts.d.ts +6 -0
  79. package/dist/workbook-contracts.d.ts.map +1 -1
  80. package/dist/workbook-models.d.ts.map +1 -1
  81. package/package.json +8 -8
  82. package/dist/chunks/workbook-photo-service-C6mbUUp6.js.map +0 -1
@@ -0,0 +1,125 @@
1
+ import type { DatabaseInterface } from '@happyvertical/sql';
2
+ import { type CourseAuthoringActor, type CourseAuthoringAuthorizer } from './course-authoring-contracts.js';
3
+ import { CourseAuthoringService, type CourseAuthoringServiceOptions } from './course-authoring-service.js';
4
+ import { type LearningObjectiveInput, type LearningObjectiveView, type QuestionContentInput, type QuestionHeadView, type QuestionRevisionView, type ReleasedLessonView, type ResolvedQuestionRevisions, type WorksheetBundle } from './question-contracts.js';
5
+ export interface QuestionAuthoringServiceOptions extends CourseAuthoringServiceOptions {
6
+ /** Trusted concept ids; when supplied, question and objective concepts must belong. */
7
+ conceptVocabulary?: ReadonlyArray<{
8
+ id: string;
9
+ }>;
10
+ }
11
+ /**
12
+ * Actor-bound authoring of immutable questions and stable learning objectives.
13
+ * It shares `CourseAuthoringService`'s authorizer and actions: writes need
14
+ * `education.course.author` (plus `generate` for generated provenance); reads of
15
+ * answer keys need `education.course.read-draft`.
16
+ */
17
+ export declare class QuestionAuthoringService extends CourseAuthoringService {
18
+ private readonly vocabulary;
19
+ constructor(db: DatabaseInterface, authorizer: CourseAuthoringAuthorizer, options?: QuestionAuthoringServiceOptions);
20
+ private normalize;
21
+ private normalizeObjective;
22
+ private authorizeWrite;
23
+ /** Objectives and media named by a revision must exist in the same tenant. */
24
+ private requireReferences;
25
+ private lock;
26
+ private head;
27
+ /** Creates the stable question identity and its first immutable revision. */
28
+ createQuestion(request: CourseAuthoringActor & {
29
+ requestKey: string;
30
+ courseId?: string;
31
+ content: QuestionContentInput;
32
+ }): Promise<QuestionHeadView>;
33
+ private appendQuestionRevision;
34
+ /**
35
+ * Appends an immutable revision when `expectedHeadRevisionId` is still the
36
+ * head. A retried key replays its original result; the same key with a
37
+ * different payload is a typed conflict.
38
+ */
39
+ saveQuestionRevision(request: CourseAuthoringActor & {
40
+ questionId: string;
41
+ expectedHeadRevisionId: string;
42
+ requestKey: string;
43
+ content: QuestionContentInput;
44
+ }): Promise<QuestionHeadView>;
45
+ /** Replaces a question's objective links by appending a revision. */
46
+ linkObjectives(request: CourseAuthoringActor & {
47
+ questionId: string;
48
+ expectedHeadRevisionId: string;
49
+ requestKey: string;
50
+ objectiveIds: string[];
51
+ }): Promise<QuestionHeadView>;
52
+ private saveRevision;
53
+ private questionRow;
54
+ private contentFromRow;
55
+ private questionRevisionView;
56
+ /** Reads a question revision (the head unless `revisionId` is given), key included. */
57
+ readQuestion(request: CourseAuthoringActor & {
58
+ questionId: string;
59
+ revisionId?: string;
60
+ }): Promise<{
61
+ head: QuestionHeadView;
62
+ revision: QuestionRevisionView;
63
+ }>;
64
+ /**
65
+ * Resolves question revision ids to reference labels for a host (e.g. a printed
66
+ * worksheet's question list). Needs `read-draft` (operation
67
+ * `resolve-question-revisions`, no course). Tenant-exact: an id that is unknown
68
+ * or belongs to another tenant is simply reported in `missing`, with no
69
+ * distinction. The result never carries answer keys, rubrics, choices, media or
70
+ * provenance. At most 200 ids; duplicates are folded; an empty list, a
71
+ * non-string or an over-long id is a validation error.
72
+ */
73
+ resolveQuestionRevisions(request: CourseAuthoringActor & {
74
+ revisionIds: string[];
75
+ }): Promise<ResolvedQuestionRevisions>;
76
+ /**
77
+ * Creates a stable objective identity under a tenant-unique `externalKey`. The
78
+ * same key with the same request replays; any other use of the key conflicts.
79
+ */
80
+ createLearningObjective(request: CourseAuthoringActor & {
81
+ requestKey: string;
82
+ externalKey: string;
83
+ objective: LearningObjectiveInput;
84
+ }): Promise<LearningObjectiveView>;
85
+ private appendObjective;
86
+ /** Appends new wording; the objective's id and `externalKey` never change. */
87
+ saveLearningObjectiveRevision(request: CourseAuthoringActor & {
88
+ objectiveId: string;
89
+ expectedHeadRevisionId: string;
90
+ requestKey: string;
91
+ objective: LearningObjectiveInput;
92
+ }): Promise<LearningObjectiveView>;
93
+ private objectiveRow;
94
+ private objectiveView;
95
+ /** Reads an objective by id or by its stable external key. */
96
+ readLearningObjective(request: CourseAuthoringActor & {
97
+ objectiveId?: string;
98
+ externalKey?: string;
99
+ }): Promise<LearningObjectiveView>;
100
+ /**
101
+ * Render input for one lesson of a release, from its pinned question
102
+ * revisions. `learner` omits keys and rubrics by type. Both audiences need
103
+ * `read-draft` here; learner delivery is a host path that calls
104
+ * `buildLearnerWorksheet` over data it already authorized.
105
+ */
106
+ getWorksheet(request: CourseAuthoringActor & {
107
+ releaseId: string;
108
+ lessonKey: string;
109
+ audience: 'learner' | 'guardian';
110
+ }): Promise<WorksheetBundle>;
111
+ /** The release lesson's immutable revision row and keyed worksheet inputs. */
112
+ private releasedLessonInput;
113
+ /**
114
+ * Authoring/guardian read of one released lesson: the full lesson revision
115
+ * (materials, provenance, ordered question refs, layout params) and the keyed
116
+ * worksheet bundle (answer keys and rubrics included). Needs `read-draft`;
117
+ * learners use `QuestionResponseService.readReleasedLesson`, which is keyless
118
+ * and limited to their effective lessons.
119
+ */
120
+ readReleasedLesson(request: CourseAuthoringActor & {
121
+ releaseId: string;
122
+ lessonKey: string;
123
+ }): Promise<ReleasedLessonView>;
124
+ }
125
+ //# sourceMappingURL=question-authoring-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-authoring-service.d.ts","sourceRoot":"","sources":["../src/question-authoring-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type QuestionAnswerKey, type QuestionChoice, type QuestionContentInput, type QuestionField, type QuestionMediaRef, type QuestionProvenance, type QuestionResponseType, type QuestionRubric, type QuestionSubpart } from './question-contracts.js';
2
+ export interface NormalizedQuestionContent {
3
+ prompt: string;
4
+ responseType: QuestionResponseType;
5
+ choices: QuestionChoice[];
6
+ subparts: QuestionSubpart[];
7
+ media: Required<QuestionMediaRef>[];
8
+ objectiveIds: string[];
9
+ conceptIds: string[];
10
+ /** Null when no key was supplied; never an empty key. */
11
+ answerKey: QuestionAnswerKey | null;
12
+ rubric: QuestionRubric | null;
13
+ pointsPossible: number | null;
14
+ provenance: QuestionProvenance;
15
+ /** Effective provenance of every present field; absent fields have no entry. */
16
+ fieldProvenance: Partial<Record<QuestionField, QuestionProvenance>>;
17
+ }
18
+ /**
19
+ * Validates and normalizes authored question content. Pure; ownership checks
20
+ * (assets, objectives) are the caller's. Throws `CourseAuthoringValidationError`.
21
+ */
22
+ export declare function normalizeQuestionContent(input: QuestionContentInput, options?: {
23
+ conceptVocabulary?: ReadonlySet<string>;
24
+ }): NormalizedQuestionContent;
25
+ //# sourceMappingURL=question-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-content.d.ts","sourceRoot":"","sources":["../src/question-content.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,oBAAoB,CAAC;IACnC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;IACpC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,yDAAyD;IACzD,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,gFAAgF;IAChF,eAAe,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC,CAAC;CACrE;AAyED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,GAAE;IAAE,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAO,GACxD,yBAAyB,CAuP3B"}
@@ -0,0 +1,240 @@
1
+ import { type CourseAuthoringActor, CourseAuthoringError, type CourseLessonCompletion, type CourseLessonRevisionView, type CourseLessonType } from './course-authoring-contracts.js';
2
+ import type { QuestionRubric } from './question-rubric.js';
3
+ export type { QuestionRubric, QuestionRubricCriterion, } from './question-rubric.js';
4
+ /** Supplied by the author, or inferred/generated/extracted by a tool. */
5
+ export type QuestionProvenance = 'supplied' | 'inferred' | 'generated' | 'edited' | 'extracted';
6
+ export declare const QUESTION_PROVENANCES: readonly QuestionProvenance[];
7
+ export type QuestionResponseType = 'short-answer' | 'numeric' | 'multiple-choice' | 'multi-select' | 'true-false' | 'extended' | 'multi-part';
8
+ export declare const QUESTION_RESPONSE_TYPES: readonly QuestionResponseType[];
9
+ /** Where a learner completed the question; same completion vocabulary as workbooks. */
10
+ export type QuestionCompletionMode = 'printable' | 'online' | 'interactive';
11
+ export declare const QUESTION_COMPLETION_MODES: readonly QuestionCompletionMode[];
12
+ export type QuestionAssistance = 'independent' | 'assisted' | 'unknown';
13
+ /** Fields that carry their own provenance. A field that is absent has no entry. */
14
+ export type QuestionField = 'prompt' | 'responseType' | 'choices' | 'subparts' | 'media' | 'objectives' | 'concepts' | 'answerKey' | 'rubric' | 'pointsPossible';
15
+ export declare const QUESTION_FIELDS: readonly QuestionField[];
16
+ export interface QuestionChoice {
17
+ id: string;
18
+ label: string;
19
+ }
20
+ export interface QuestionSubpart {
21
+ partKey: string;
22
+ prompt: string;
23
+ responseType?: Exclude<QuestionResponseType, 'multi-part'>;
24
+ pointsPossible?: number;
25
+ }
26
+ export interface QuestionMediaRef {
27
+ assetId: string;
28
+ role?: 'figure' | 'passage' | 'audio' | 'other';
29
+ alt?: string;
30
+ }
31
+ /** Atomic accepted answer(s). At least one member is required; never `{}`. */
32
+ export interface QuestionAnswerAtom {
33
+ correctChoiceIds?: string[];
34
+ acceptedAnswers?: string[];
35
+ numeric?: {
36
+ value: number;
37
+ tolerance?: number;
38
+ };
39
+ }
40
+ export interface QuestionAnswerKey extends QuestionAnswerAtom {
41
+ /** Per-subpart keys by `partKey`. */
42
+ parts?: Record<string, QuestionAnswerAtom>;
43
+ explanation?: string;
44
+ }
45
+ /** Everything an author states about one question revision. */
46
+ export interface QuestionContentInput {
47
+ prompt: string;
48
+ responseType: QuestionResponseType;
49
+ choices?: QuestionChoice[];
50
+ subparts?: QuestionSubpart[];
51
+ media?: QuestionMediaRef[];
52
+ /** Stable `LearningObjective` identity ids. */
53
+ objectiveIds?: string[];
54
+ conceptIds?: string[];
55
+ /** Omit (or null) when no key exists: a missing key stays missing. */
56
+ answerKey?: QuestionAnswerKey | null;
57
+ rubric?: QuestionRubric | null;
58
+ pointsPossible?: number | null;
59
+ /** Default for every present field without its own entry. */
60
+ provenance: QuestionProvenance;
61
+ fieldProvenance?: Partial<Record<QuestionField, QuestionProvenance>>;
62
+ }
63
+ export interface QuestionRevisionView {
64
+ id: string;
65
+ questionId: string;
66
+ parentRevisionId: string | null;
67
+ sequence: number;
68
+ prompt: string;
69
+ responseType: QuestionResponseType;
70
+ choices: QuestionChoice[];
71
+ subparts: QuestionSubpart[];
72
+ media: QuestionMediaRef[];
73
+ objectives: Array<{
74
+ objectiveId: string;
75
+ externalKey: string;
76
+ revisionId: string;
77
+ statement: string;
78
+ }>;
79
+ conceptIds: string[];
80
+ /** Null means no key was ever supplied; it is never an empty/zero key. */
81
+ answerKey: QuestionAnswerKey | null;
82
+ rubric: QuestionRubric | null;
83
+ pointsPossible: number | null;
84
+ provenance: QuestionProvenance;
85
+ fieldProvenance: Partial<Record<QuestionField, QuestionProvenance>>;
86
+ authorUserId: string;
87
+ delegatingGuardianUserId: string | null;
88
+ delegationId: string | null;
89
+ recordedAt: string;
90
+ }
91
+ /** Most question revision ids one `resolveQuestionRevisions` call accepts. */
92
+ export declare const MAX_RESOLVE_QUESTION_REVISIONS = 200;
93
+ /** Longest `promptSummary`, in characters. */
94
+ export declare const QUESTION_PROMPT_SUMMARY_LENGTH = 200;
95
+ /**
96
+ * A question revision as a host reference label. Never carries an answer key,
97
+ * rubric, choices, media or provenance.
98
+ */
99
+ export interface QuestionRevisionSummary {
100
+ revisionId: string;
101
+ questionId: string;
102
+ sequence: number;
103
+ responseType: QuestionResponseType;
104
+ /** Plain-text excerpt of the prompt: whitespace collapsed, at most 200 characters. */
105
+ promptSummary: string;
106
+ /** Stable objective external keys; present only when the revision links objectives. */
107
+ learningObjectiveKeys?: string[];
108
+ }
109
+ export interface ResolvedQuestionRevisions {
110
+ /** Found revisions, in the order of the first occurrence of each requested id. */
111
+ items: QuestionRevisionSummary[];
112
+ /** Requested ids with no revision in this tenant (foreign and unknown are alike). */
113
+ missing: string[];
114
+ }
115
+ export interface QuestionHeadView {
116
+ questionId: string;
117
+ /** The expected-head token for the next save. */
118
+ headRevisionId: string;
119
+ sequence: number;
120
+ }
121
+ export interface LearningObjectiveInput {
122
+ statement: string;
123
+ conceptIds?: string[];
124
+ subject?: string;
125
+ levelMin?: number;
126
+ levelMax?: number;
127
+ provenance?: QuestionProvenance;
128
+ }
129
+ export interface LearningObjectiveView {
130
+ id: string;
131
+ /** Stable key shared with consumers (for example hearthed.org#35). */
132
+ externalKey: string;
133
+ headRevisionId: string;
134
+ sequence: number;
135
+ statement: string;
136
+ conceptIds: string[];
137
+ subject: string;
138
+ levelMin: number;
139
+ levelMax: number;
140
+ provenance: QuestionProvenance;
141
+ }
142
+ /** One ordered question in a lesson revision. Order is array order. */
143
+ export interface LessonQuestionRefInput {
144
+ questionRevisionId: string;
145
+ section?: string;
146
+ column?: number;
147
+ /** Source page/region where known; normalized `rect` is x, y, width, height. */
148
+ anchor?: {
149
+ assetId?: string;
150
+ page?: number;
151
+ rect?: [number, number, number, number];
152
+ };
153
+ }
154
+ export type LessonLayoutParams = Record<string, string | number | boolean>;
155
+ /** Learner-facing item. Built from an allowlist, so keys and rubrics cannot leak. */
156
+ export interface LearnerQuestionItem {
157
+ ordinal: number;
158
+ questionId: string;
159
+ questionRevisionId: string;
160
+ section: string;
161
+ column: number;
162
+ anchor: LessonQuestionRefInput['anchor'] | null;
163
+ prompt: string;
164
+ responseType: QuestionResponseType;
165
+ choices: QuestionChoice[];
166
+ subparts: QuestionSubpart[];
167
+ media: QuestionMediaRef[];
168
+ pointsPossible: number | null;
169
+ }
170
+ export interface GuardianQuestionItem extends LearnerQuestionItem {
171
+ answerKey: QuestionAnswerKey | null;
172
+ rubric: QuestionRubric | null;
173
+ fieldProvenance: Partial<Record<QuestionField, QuestionProvenance>>;
174
+ }
175
+ interface WorksheetBundleBase {
176
+ /** Digest of ordered question revision ids and layout params. */
177
+ worksheetVersionId: string;
178
+ lessonRevisionId: string;
179
+ layoutParams: LessonLayoutParams;
180
+ }
181
+ export interface LearnerWorksheetBundle extends WorksheetBundleBase {
182
+ audience: 'learner';
183
+ items: LearnerQuestionItem[];
184
+ }
185
+ export interface GuardianWorksheetBundle extends WorksheetBundleBase {
186
+ audience: 'guardian';
187
+ items: GuardianQuestionItem[];
188
+ }
189
+ export type WorksheetBundle = LearnerWorksheetBundle | GuardianWorksheetBundle;
190
+ export type QuestionActor = CourseAuthoringActor;
191
+ /**
192
+ * Authoring/guardian read of one released lesson (`read-draft`): the full lesson
193
+ * revision (materials and provenance included) and the keyed worksheet bundle.
194
+ */
195
+ export type ReleasedLessonView = Readonly<{
196
+ releaseId: string;
197
+ courseId: string;
198
+ lessonKey: string;
199
+ lessonId: string;
200
+ sectionId: string;
201
+ lessonRevisionId: string;
202
+ revision: CourseLessonRevisionView;
203
+ worksheet: GuardianWorksheetBundle;
204
+ }>;
205
+ /**
206
+ * Learner-safe read of one effective lesson. Built from an allowlist: no key,
207
+ * rubric, provenance, material, source locator or licence detail. The body of a
208
+ * personal-use-copy lesson is withheld (empty, `bodyWithheld`).
209
+ */
210
+ export type LearnerLessonView = Readonly<{
211
+ enrollmentId: string;
212
+ releaseId: string;
213
+ lessonKey: string;
214
+ lessonId: string;
215
+ lessonRevisionId: string;
216
+ title: string;
217
+ body: string;
218
+ bodyWithheld: boolean;
219
+ lessonType: CourseLessonType;
220
+ completionRule: CourseLessonCompletion;
221
+ estimatedMinutes: number;
222
+ /** True when a started lesson stays on an older release than the current pin. */
223
+ pinnedToOlderRelease: boolean;
224
+ worksheet: LearnerWorksheetBundle;
225
+ }>;
226
+ export declare class QuestionNotFoundError extends CourseAuthoringError {
227
+ constructor();
228
+ }
229
+ export declare class LearningObjectiveNotFoundError extends CourseAuthoringError {
230
+ constructor();
231
+ }
232
+ export declare class LearningObjectiveKeyConflictError extends CourseAuthoringError {
233
+ constructor();
234
+ }
235
+ /** A lesson revision named a question revision that is missing or foreign. */
236
+ export declare class QuestionReferenceError extends CourseAuthoringError {
237
+ readonly references: readonly string[];
238
+ constructor(references: readonly string[]);
239
+ }
240
+ //# sourceMappingURL=question-contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-contracts.d.ts","sourceRoot":"","sources":["../src/question-contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { SmrtCollection, SmrtObject, type SmrtSaveOptions } from '@happyvertical/smrt-core';
2
+ /** Stable learning-objective identity: survives wording changes, variants and themes. */
3
+ export declare class LearningObjective extends SmrtObject {
4
+ tenantId: string;
5
+ /** Stable coordination key (for example with hearthed.org#35); unique per tenant. */
6
+ externalKey: string;
7
+ createdByUserId: string;
8
+ requestKey: string;
9
+ recordedAt: Date;
10
+ constructor(options?: Record<string, unknown>);
11
+ delete(): Promise<void>;
12
+ save(options?: SmrtSaveOptions): Promise<this>;
13
+ }
14
+ export declare class LearningObjectiveCollection extends SmrtCollection<LearningObjective> {
15
+ static readonly _itemClass: typeof LearningObjective;
16
+ }
17
+ /** Append-only objective wording; the highest sequence is the head. */
18
+ export declare class LearningObjectiveRevision extends SmrtObject {
19
+ tenantId: string;
20
+ objectiveId: string;
21
+ parentRevisionId: string | null;
22
+ sequence: number;
23
+ statement: string;
24
+ conceptIdsJson: string;
25
+ subject: string;
26
+ levelMin: number;
27
+ levelMax: number;
28
+ provenance: string;
29
+ authorUserId: string;
30
+ delegatingGuardianUserId: string;
31
+ delegationId: string;
32
+ requestKey: string;
33
+ payloadDigest: string;
34
+ recordedAt: Date;
35
+ constructor(options?: Record<string, unknown>);
36
+ delete(): Promise<void>;
37
+ save(options?: SmrtSaveOptions): Promise<this>;
38
+ }
39
+ export declare class LearningObjectiveRevisionCollection extends SmrtCollection<LearningObjectiveRevision> {
40
+ static readonly _itemClass: typeof LearningObjectiveRevision;
41
+ }
42
+ /** Stable question identity. Content lives only in immutable revisions. */
43
+ export declare class Question extends SmrtObject {
44
+ tenantId: string;
45
+ /** Authored course this question was written for; reuse across courses is allowed. */
46
+ courseId: string | null;
47
+ createdByUserId: string;
48
+ requestKey: string;
49
+ recordedAt: Date;
50
+ constructor(options?: Record<string, unknown>);
51
+ delete(): Promise<void>;
52
+ save(options?: SmrtSaveOptions): Promise<this>;
53
+ }
54
+ export declare class QuestionCollection extends SmrtCollection<Question> {
55
+ static readonly _itemClass: typeof Question;
56
+ }
57
+ /**
58
+ * Immutable question snapshot. A missing answer key or rubric is stored as NULL
59
+ * and never as an empty object, zero or an inferred value.
60
+ */
61
+ export declare class QuestionRevision extends SmrtObject {
62
+ tenantId: string;
63
+ questionId: string;
64
+ parentRevisionId: string | null;
65
+ sequence: number;
66
+ prompt: string;
67
+ responseType: string;
68
+ choicesJson: string;
69
+ subpartsJson: string;
70
+ mediaJson: string;
71
+ objectiveIdsJson: string;
72
+ conceptIdsJson: string;
73
+ answerKeyJson: string | null;
74
+ rubricJson: string | null;
75
+ pointsPossible: number | null;
76
+ provenance: string;
77
+ fieldProvenanceJson: string;
78
+ authorUserId: string;
79
+ delegatingGuardianUserId: string;
80
+ delegationId: string;
81
+ requestKey: string;
82
+ payloadDigest: string;
83
+ recordedAt: Date;
84
+ constructor(options?: Record<string, unknown>);
85
+ delete(): Promise<void>;
86
+ save(options?: SmrtSaveOptions): Promise<this>;
87
+ }
88
+ export declare class QuestionRevisionCollection extends SmrtCollection<QuestionRevision> {
89
+ static readonly _itemClass: typeof QuestionRevision;
90
+ }
91
+ /**
92
+ * Append-only learner response to one exact question revision. A correction is a
93
+ * new row naming its predecessor; a response never rewrites question content.
94
+ */
95
+ export declare class QuestionResponse extends SmrtObject {
96
+ tenantId: string;
97
+ learnerId: string;
98
+ enrollmentId: string;
99
+ questionRevisionId: string;
100
+ lessonRevisionId: string | null;
101
+ /** The worksheet render the learner saw, for scan matching. */
102
+ worksheetVersionId: string;
103
+ submissionId: string | null;
104
+ previousResponseId: string | null;
105
+ /** Groups an attempt and its corrections. */
106
+ episodeId: string;
107
+ completionMode: string;
108
+ assistance: string;
109
+ responseJson: string;
110
+ /** 1-based attempt (episode) number per learner and question revision. */
111
+ attemptNumber: number;
112
+ actorUserId: string;
113
+ requestKey: string;
114
+ /** Digest of the request that wrote this row; empty for rows written directly. */
115
+ payloadDigest: string;
116
+ recordedAt: Date;
117
+ constructor(options?: Record<string, unknown>);
118
+ delete(): Promise<void>;
119
+ save(options?: SmrtSaveOptions): Promise<this>;
120
+ }
121
+ export declare class QuestionResponseCollection extends SmrtCollection<QuestionResponse> {
122
+ static readonly _itemClass: typeof QuestionResponse;
123
+ }
124
+ //# sourceMappingURL=question-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-models.d.ts","sourceRoot":"","sources":["../src/question-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,UAAU,EACV,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AA2DlC,yFAAyF;AACzF,qBAMa,iBAAkB,SAAQ,UAAU;IACnC,QAAQ,SAAM;IAC1B,qFAAqF;IACrF,WAAW,SAAM;IACjB,eAAe,SAAM;IACrB,UAAU,SAAM;IAChB,UAAU,OAAc;gBACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAU9D;AACD,qBAAa,2BAA4B,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IAChF,MAAM,CAAC,QAAQ,CAAC,UAAU,2BAAqB;CAChD;AAED,uEAAuE;AACvE,qBAaa,yBAA0B,SAAQ,UAAU;IAC3C,QAAQ,SAAM;IAC2B,WAAW,SAAM;IAEtE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAQ;IACvC,QAAQ,SAAK;IACY,SAAS,SAAM;IACf,cAAc,SAAQ;IAC/C,OAAO,SAAM;IACb,QAAQ,SAAK;IACb,QAAQ,SAAK;IACb,UAAU,SAAc;IACxB,YAAY,SAAM;IAClB,wBAAwB,SAAM;IAC9B,YAAY,SAAM;IAClB,UAAU,SAAM;IAChB,aAAa,SAAM;IACnB,UAAU,OAAc;gBACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CA4B9D;AACD,qBAAa,mCAAoC,SAAQ,cAAc,CAAC,yBAAyB,CAAC;IAChG,MAAM,CAAC,QAAQ,CAAC,UAAU,mCAA6B;CACxD;AAED,2EAA2E;AAC3E,qBAMa,QAAS,SAAQ,UAAU;IAC1B,QAAQ,SAAM;IAC1B,sFAAsF;IAC5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACzE,eAAe,SAAM;IACrB,UAAU,SAAM;IAChB,UAAU,OAAc;gBACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAS9D;AACD,qBAAa,kBAAmB,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAC9D,MAAM,CAAC,QAAQ,CAAC,UAAU,kBAAY;CACvC;AAED;;;GAGG;AACH,qBAaa,gBAAiB,SAAQ,UAAU;IAClC,QAAQ,SAAM;IACkB,UAAU,SAAM;IACR,gBAAgB,EAChE,MAAM,GACN,IAAI,CAAQ;IAChB,QAAQ,SAAK;IACY,MAAM,SAAM;IACrC,YAAY,SAAkB;IACL,WAAW,SAAQ;IACnB,YAAY,SAAQ;IACpB,SAAS,SAAQ;IACjB,gBAAgB,SAAQ;IACxB,cAAc,SAAQ;IACN,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IACpC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAClE;IACP,UAAU,SAAc;IACC,mBAAmB,SAAQ;IACpD,YAAY,SAAM;IAClB,wBAAwB,SAAM;IAC9B,YAAY,SAAM;IAClB,UAAU,SAAM;IAChB,aAAa,SAAM;IACnB,UAAU,OAAc;gBACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAsC9D;AACD,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;CAC/C;AAED;;;GAGG;AACH,qBAMa,gBAAiB,SAAQ,UAAU;IAClC,QAAQ,SAAM;IACiB,SAAS,SAAM;IACZ,YAAY,SAAM;IACZ,kBAAkB,SAAM;IAC1B,gBAAgB,EAC9D,MAAM,GACN,IAAI,CAAQ;IAChB,+DAA+D;IAC/D,kBAAkB,SAAM;IACsB,YAAY,EAAE,MAAM,GAAG,IAAI,CAClE;IAC6C,kBAAkB,EAClE,MAAM,GACN,IAAI,CAAQ;IAChB,6CAA6C;IAC7C,SAAS,SAAM;IACf,cAAc,SAAY;IAC1B,UAAU,SAAa;IACE,YAAY,SAAQ;IAC7C,0EAA0E;IAC1E,aAAa,SAAK;IAClB,WAAW,SAAM;IACjB,UAAU,SAAM;IAChB,kFAAkF;IAClF,aAAa,SAAM;IACnB,UAAU,OAAc;gBACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAsC9D;AACD,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;CAC/C"}
@@ -0,0 +1,20 @@
1
+ import type { GuardianWorksheetBundle, LearnerWorksheetBundle, LessonLayoutParams, LessonQuestionRefInput, QuestionRevisionView } from './question-contracts.js';
2
+ export declare const canonical: (value: unknown) => string;
3
+ /**
4
+ * Deterministic id of one worksheet layout: the ordered question revisions with
5
+ * their placement plus the layout params. Printable and online renders of the
6
+ * same inputs share it, so a later scan can be matched to the exact revisions.
7
+ */
8
+ export declare function worksheetVersionId(refs: readonly LessonQuestionRefInput[], layoutParams?: LessonLayoutParams): string;
9
+ export interface WorksheetRenderInput {
10
+ lessonRevisionId: string;
11
+ refs: readonly LessonQuestionRefInput[];
12
+ layoutParams?: LessonLayoutParams;
13
+ /** The pinned revisions, by id. Every ref must resolve. */
14
+ revisions: ReadonlyMap<string, QuestionRevisionView>;
15
+ }
16
+ /** Render input for learners (printable or online); answer keys are excluded by type. */
17
+ export declare function buildLearnerWorksheet(input: WorksheetRenderInput): LearnerWorksheetBundle;
18
+ /** Guardian/author bundle: the same items plus keys, rubrics and provenance. */
19
+ export declare function buildGuardianWorksheet(input: WorksheetRenderInput): GuardianWorksheetBundle;
20
+ //# sourceMappingURL=question-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-render.d.ts","sourceRoot":"","sources":["../src/question-render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,uBAAuB,EAEvB,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,yBAAyB,CAAC;AAEjC,eAAO,MAAM,SAAS,GAAI,OAAO,OAAO,KAAG,MAOxC,CAAC;AAEJ;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,sBAAsB,EAAE,EACvC,YAAY,GAAE,kBAAuB,GACpC,MAAM,CAWR;AAwBD,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACxC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,2DAA2D;IAC3D,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACtD;AAUD,yFAAyF;AACzF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,oBAAoB,GAC1B,sBAAsB,CASxB;AAED,gFAAgF;AAChF,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,oBAAoB,GAC1B,uBAAuB,CAgBzB"}
@@ -0,0 +1,54 @@
1
+ import { CourseAuthoringError } from './course-authoring-contracts.js';
2
+ import type { GuardianWorksheetBundle, LearnerWorksheetBundle, QuestionAssistance, QuestionCompletionMode } from './question-contracts.js';
3
+ /**
4
+ * The learner's answer to one question. Only these members are accepted so a
5
+ * response can never smuggle other data; `choiceIds` must name the revision's
6
+ * choices and `parts` keys its subparts.
7
+ */
8
+ export interface QuestionResponseContent {
9
+ text?: string;
10
+ numeric?: number;
11
+ choiceIds?: string[];
12
+ parts?: Record<string, {
13
+ text?: string;
14
+ numeric?: number;
15
+ choiceIds?: string[];
16
+ }>;
17
+ }
18
+ /** Data-only view of one append-only response row. It carries no key or rubric. */
19
+ export interface QuestionResponseView {
20
+ id: string;
21
+ learnerId: string;
22
+ enrollmentId: string;
23
+ lessonRevisionId: string | null;
24
+ questionRevisionId: string;
25
+ worksheetVersionId: string;
26
+ /** Groups one attempt and its corrections. */
27
+ episodeId: string;
28
+ attemptNumber: number;
29
+ /** The response this row corrects, or null for a new attempt. */
30
+ previousResponseId: string | null;
31
+ completionMode: QuestionCompletionMode;
32
+ assistance: QuestionAssistance;
33
+ response: QuestionResponseContent;
34
+ actorUserId: string;
35
+ /** True when the author is not the learner (a guardian correction). */
36
+ byGuardian: boolean;
37
+ recordedAt: string;
38
+ }
39
+ /** Learner reads get the keyless bundle; guardians get the keyed one. */
40
+ export interface LessonQuestionResponses {
41
+ worksheet: LearnerWorksheetBundle | GuardianWorksheetBundle;
42
+ responses: QuestionResponseView[];
43
+ }
44
+ export declare class QuestionResponseValidationError extends CourseAuthoringError {
45
+ constructor(message: string);
46
+ }
47
+ /** The question revision is not in the enrollment's effective lesson set. */
48
+ export declare class QuestionResponseScopeError extends CourseAuthoringError {
49
+ constructor();
50
+ }
51
+ export declare class QuestionResponseNotFoundError extends CourseAuthoringError {
52
+ constructor();
53
+ }
54
+ //# sourceMappingURL=question-response-contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-response-contracts.d.ts","sourceRoot":"","sources":["../src/question-response-contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CACZ,MAAM,EACN;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAC1D,CAAC;CACH;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,sBAAsB,CAAC;IACvC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,sBAAsB,GAAG,uBAAuB,CAAC;IAC5D,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC;AAED,qBAAa,+BAAgC,SAAQ,oBAAoB;gBAC3D,OAAO,EAAE,MAAM;CAG5B;AACD,6EAA6E;AAC7E,qBAAa,0BAA2B,SAAQ,oBAAoB;;CAOnE;AACD,qBAAa,6BAA8B,SAAQ,oBAAoB;;CAItE"}