@contractspec/module.learning-journey 1.57.0 → 1.59.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/dist/browser/contracts/index.js +578 -0
- package/dist/browser/contracts/models.js +193 -0
- package/dist/browser/contracts/onboarding.js +417 -0
- package/dist/browser/contracts/operations.js +326 -0
- package/dist/browser/contracts/shared.js +5 -0
- package/dist/browser/docs/index.js +124 -0
- package/dist/browser/docs/learning-journey.docblock.js +124 -0
- package/dist/browser/engines/index.js +526 -0
- package/dist/browser/engines/srs.js +198 -0
- package/dist/browser/engines/streak.js +159 -0
- package/dist/browser/engines/xp.js +171 -0
- package/dist/browser/entities/ai.js +343 -0
- package/dist/browser/entities/course.js +276 -0
- package/dist/browser/entities/flashcard.js +222 -0
- package/dist/browser/entities/gamification.js +340 -0
- package/dist/browser/entities/index.js +2136 -0
- package/dist/browser/entities/learner.js +329 -0
- package/dist/browser/entities/onboarding.js +301 -0
- package/dist/browser/entities/quiz.js +304 -0
- package/dist/browser/events.js +423 -0
- package/dist/browser/index.js +3833 -0
- package/dist/browser/learning-journey.capability.js +40 -0
- package/dist/browser/learning-journey.feature.js +56 -0
- package/dist/browser/track-spec.js +0 -0
- package/dist/contracts/index.d.ts +5 -5
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +578 -5
- package/dist/contracts/models.d.ts +426 -431
- package/dist/contracts/models.d.ts.map +1 -1
- package/dist/contracts/models.js +178 -372
- package/dist/contracts/onboarding.d.ts +621 -627
- package/dist/contracts/onboarding.d.ts.map +1 -1
- package/dist/contracts/onboarding.js +404 -388
- package/dist/contracts/operations.d.ts +243 -249
- package/dist/contracts/operations.d.ts.map +1 -1
- package/dist/contracts/operations.js +324 -148
- package/dist/contracts/shared.d.ts +1 -4
- package/dist/contracts/shared.d.ts.map +1 -1
- package/dist/contracts/shared.js +6 -6
- package/dist/docs/index.d.ts +2 -1
- package/dist/docs/index.d.ts.map +1 -0
- package/dist/docs/index.js +125 -1
- package/dist/docs/learning-journey.docblock.d.ts +2 -1
- package/dist/docs/learning-journey.docblock.d.ts.map +1 -0
- package/dist/docs/learning-journey.docblock.js +47 -58
- package/dist/engines/index.d.ts +4 -4
- package/dist/engines/index.d.ts.map +1 -0
- package/dist/engines/index.js +526 -4
- package/dist/engines/srs.d.ts +89 -92
- package/dist/engines/srs.d.ts.map +1 -1
- package/dist/engines/srs.js +197 -217
- package/dist/engines/streak.d.ts +84 -87
- package/dist/engines/streak.d.ts.map +1 -1
- package/dist/engines/streak.js +158 -192
- package/dist/engines/xp.d.ts +80 -83
- package/dist/engines/xp.d.ts.map +1 -1
- package/dist/engines/xp.js +170 -211
- package/dist/entities/ai.d.ts +199 -204
- package/dist/entities/ai.d.ts.map +1 -1
- package/dist/entities/ai.js +336 -368
- package/dist/entities/course.d.ts +149 -154
- package/dist/entities/course.d.ts.map +1 -1
- package/dist/entities/course.js +267 -306
- package/dist/entities/flashcard.d.ts +144 -149
- package/dist/entities/flashcard.d.ts.map +1 -1
- package/dist/entities/flashcard.js +217 -243
- package/dist/entities/gamification.d.ts +197 -202
- package/dist/entities/gamification.d.ts.map +1 -1
- package/dist/entities/gamification.js +331 -382
- package/dist/entities/index.d.ts +613 -618
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/index.js +2135 -43
- package/dist/entities/learner.d.ts +191 -196
- package/dist/entities/learner.d.ts.map +1 -1
- package/dist/entities/learner.js +322 -357
- package/dist/entities/onboarding.d.ts +164 -169
- package/dist/entities/onboarding.d.ts.map +1 -1
- package/dist/entities/onboarding.js +296 -301
- package/dist/entities/quiz.d.ts +184 -189
- package/dist/entities/quiz.d.ts.map +1 -1
- package/dist/entities/quiz.js +296 -361
- package/dist/events.d.ts +608 -614
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +421 -687
- package/dist/index.d.ts +8 -20
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3834 -22
- package/dist/learning-journey.capability.d.ts +3 -8
- package/dist/learning-journey.capability.d.ts.map +1 -1
- package/dist/learning-journey.capability.js +41 -46
- package/dist/learning-journey.feature.d.ts +1 -6
- package/dist/learning-journey.feature.d.ts.map +1 -1
- package/dist/learning-journey.feature.js +55 -155
- package/dist/node/contracts/index.js +578 -0
- package/dist/node/contracts/models.js +193 -0
- package/dist/node/contracts/onboarding.js +417 -0
- package/dist/node/contracts/operations.js +326 -0
- package/dist/node/contracts/shared.js +5 -0
- package/dist/node/docs/index.js +124 -0
- package/dist/node/docs/learning-journey.docblock.js +124 -0
- package/dist/node/engines/index.js +526 -0
- package/dist/node/engines/srs.js +198 -0
- package/dist/node/engines/streak.js +159 -0
- package/dist/node/engines/xp.js +171 -0
- package/dist/node/entities/ai.js +343 -0
- package/dist/node/entities/course.js +276 -0
- package/dist/node/entities/flashcard.js +222 -0
- package/dist/node/entities/gamification.js +340 -0
- package/dist/node/entities/index.js +2136 -0
- package/dist/node/entities/learner.js +329 -0
- package/dist/node/entities/onboarding.js +301 -0
- package/dist/node/entities/quiz.js +304 -0
- package/dist/node/events.js +423 -0
- package/dist/node/index.js +3833 -0
- package/dist/node/learning-journey.capability.js +40 -0
- package/dist/node/learning-journey.feature.js +56 -0
- package/dist/node/track-spec.js +0 -0
- package/dist/track-spec.d.ts +115 -118
- package/dist/track-spec.d.ts.map +1 -1
- package/dist/track-spec.js +1 -0
- package/package.json +237 -60
- package/dist/contracts/models.js.map +0 -1
- package/dist/contracts/onboarding.js.map +0 -1
- package/dist/contracts/operations.js.map +0 -1
- package/dist/contracts/shared.js.map +0 -1
- package/dist/docs/learning-journey.docblock.js.map +0 -1
- package/dist/engines/srs.js.map +0 -1
- package/dist/engines/streak.js.map +0 -1
- package/dist/engines/xp.js.map +0 -1
- package/dist/entities/ai.js.map +0 -1
- package/dist/entities/course.js.map +0 -1
- package/dist/entities/flashcard.js.map +0 -1
- package/dist/entities/gamification.js.map +0 -1
- package/dist/entities/index.js.map +0 -1
- package/dist/entities/learner.js.map +0 -1
- package/dist/entities/onboarding.js.map +0 -1
- package/dist/entities/quiz.js.map +0 -1
- package/dist/events.js.map +0 -1
- package/dist/learning-journey.capability.js.map +0 -1
- package/dist/learning-journey.feature.js.map +0 -1
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// src/contracts/shared.ts
|
|
2
|
+
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
3
|
+
|
|
4
|
+
// src/contracts/models.ts
|
|
5
|
+
import { ScalarTypeEnum, defineSchemaModel } from "@contractspec/lib.schema";
|
|
6
|
+
var CourseModel = defineSchemaModel({
|
|
7
|
+
name: "Course",
|
|
8
|
+
description: "A learning course",
|
|
9
|
+
fields: {
|
|
10
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
11
|
+
title: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
12
|
+
slug: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
13
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
14
|
+
difficulty: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
15
|
+
status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
16
|
+
estimatedDuration: {
|
|
17
|
+
type: ScalarTypeEnum.Int_unsecure(),
|
|
18
|
+
isOptional: true
|
|
19
|
+
},
|
|
20
|
+
thumbnailUrl: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
21
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
var LearnerModel = defineSchemaModel({
|
|
25
|
+
name: "Learner",
|
|
26
|
+
description: "A learner profile",
|
|
27
|
+
fields: {
|
|
28
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
29
|
+
userId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
30
|
+
displayName: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
31
|
+
level: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
32
|
+
totalXp: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
33
|
+
currentStreak: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
34
|
+
longestStreak: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
35
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
var EnrollmentModel = defineSchemaModel({
|
|
39
|
+
name: "Enrollment",
|
|
40
|
+
description: "A course enrollment",
|
|
41
|
+
fields: {
|
|
42
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
43
|
+
learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
44
|
+
courseId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
45
|
+
status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
46
|
+
progress: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
47
|
+
startedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true },
|
|
48
|
+
completedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
var ProgressModel = defineSchemaModel({
|
|
52
|
+
name: "LessonProgress",
|
|
53
|
+
description: "Lesson progress",
|
|
54
|
+
fields: {
|
|
55
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
56
|
+
learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
57
|
+
lessonId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
58
|
+
status: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
59
|
+
progress: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
60
|
+
score: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
|
|
61
|
+
timeSpent: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
62
|
+
completedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
var DeckModel = defineSchemaModel({
|
|
66
|
+
name: "Deck",
|
|
67
|
+
description: "A flashcard deck",
|
|
68
|
+
fields: {
|
|
69
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
70
|
+
title: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
71
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
72
|
+
cardCount: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
73
|
+
isPublic: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
74
|
+
createdAt: { type: ScalarTypeEnum.DateTime(), isOptional: false }
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
var CardModel = defineSchemaModel({
|
|
78
|
+
name: "Card",
|
|
79
|
+
description: "A flashcard",
|
|
80
|
+
fields: {
|
|
81
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
82
|
+
deckId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
83
|
+
front: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
84
|
+
back: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
85
|
+
hints: { type: ScalarTypeEnum.JSON(), isOptional: true },
|
|
86
|
+
isDue: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
87
|
+
nextReviewAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var AchievementModel = defineSchemaModel({
|
|
91
|
+
name: "Achievement",
|
|
92
|
+
description: "An achievement",
|
|
93
|
+
fields: {
|
|
94
|
+
id: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
95
|
+
key: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
96
|
+
name: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
97
|
+
description: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
98
|
+
icon: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
99
|
+
xpReward: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
100
|
+
unlockedAt: { type: ScalarTypeEnum.DateTime(), isOptional: true }
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
var EnrollInCourseInput = defineSchemaModel({
|
|
104
|
+
name: "EnrollInCourseInput",
|
|
105
|
+
description: "Input for enrolling in a course",
|
|
106
|
+
fields: {
|
|
107
|
+
courseId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
var CompleteLessonInput = defineSchemaModel({
|
|
111
|
+
name: "CompleteLessonInput",
|
|
112
|
+
description: "Input for completing a lesson",
|
|
113
|
+
fields: {
|
|
114
|
+
lessonId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
115
|
+
score: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true },
|
|
116
|
+
timeSpent: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
var SubmitCardReviewInput = defineSchemaModel({
|
|
120
|
+
name: "SubmitCardReviewInput",
|
|
121
|
+
description: "Input for submitting a card review",
|
|
122
|
+
fields: {
|
|
123
|
+
cardId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
124
|
+
rating: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
|
|
125
|
+
responseTimeMs: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
var GetDueCardsInput = defineSchemaModel({
|
|
129
|
+
name: "GetDueCardsInput",
|
|
130
|
+
description: "Input for getting due cards",
|
|
131
|
+
fields: {
|
|
132
|
+
deckId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
|
|
133
|
+
limit: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
var GetDueCardsOutput = defineSchemaModel({
|
|
137
|
+
name: "GetDueCardsOutput",
|
|
138
|
+
description: "Output for getting due cards",
|
|
139
|
+
fields: {
|
|
140
|
+
cards: { type: CardModel, isArray: true, isOptional: false },
|
|
141
|
+
total: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
var GetLearnerDashboardInput = defineSchemaModel({
|
|
145
|
+
name: "GetLearnerDashboardInput",
|
|
146
|
+
description: "Input for getting learner dashboard",
|
|
147
|
+
fields: {
|
|
148
|
+
learnerId: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
var LearnerDashboardModel = defineSchemaModel({
|
|
152
|
+
name: "LearnerDashboard",
|
|
153
|
+
description: "Learner dashboard data",
|
|
154
|
+
fields: {
|
|
155
|
+
learner: { type: LearnerModel, isOptional: false },
|
|
156
|
+
currentStreak: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
157
|
+
dailyXpGoal: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
158
|
+
dailyXpProgress: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false },
|
|
159
|
+
activeEnrollments: {
|
|
160
|
+
type: EnrollmentModel,
|
|
161
|
+
isArray: true,
|
|
162
|
+
isOptional: false
|
|
163
|
+
},
|
|
164
|
+
recentAchievements: {
|
|
165
|
+
type: AchievementModel,
|
|
166
|
+
isArray: true,
|
|
167
|
+
isOptional: false
|
|
168
|
+
},
|
|
169
|
+
dueCardCount: { type: ScalarTypeEnum.Int_unsecure(), isOptional: false }
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
var SuccessOutput = defineSchemaModel({
|
|
173
|
+
name: "SuccessOutput",
|
|
174
|
+
description: "Generic success output",
|
|
175
|
+
fields: {
|
|
176
|
+
success: { type: ScalarTypeEnum.Boolean(), isOptional: false },
|
|
177
|
+
xpEarned: { type: ScalarTypeEnum.Int_unsecure(), isOptional: true }
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// src/contracts/operations.ts
|
|
182
|
+
import { defineCommand, defineQuery } from "@contractspec/lib.contracts";
|
|
183
|
+
var EnrollInCourseContract = defineCommand({
|
|
184
|
+
meta: {
|
|
185
|
+
key: "learning.enroll",
|
|
186
|
+
version: "1.0.0",
|
|
187
|
+
stability: "stable",
|
|
188
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
189
|
+
tags: ["learning", "enrollment"],
|
|
190
|
+
description: "Enroll in a course.",
|
|
191
|
+
goal: "Start learning a new course.",
|
|
192
|
+
context: "Called when a learner wants to start a course."
|
|
193
|
+
},
|
|
194
|
+
io: {
|
|
195
|
+
input: EnrollInCourseInput,
|
|
196
|
+
output: EnrollmentModel,
|
|
197
|
+
errors: {
|
|
198
|
+
COURSE_NOT_FOUND: {
|
|
199
|
+
description: "Course does not exist",
|
|
200
|
+
http: 404,
|
|
201
|
+
gqlCode: "COURSE_NOT_FOUND",
|
|
202
|
+
when: "Course ID is invalid"
|
|
203
|
+
},
|
|
204
|
+
ALREADY_ENROLLED: {
|
|
205
|
+
description: "Already enrolled in course",
|
|
206
|
+
http: 409,
|
|
207
|
+
gqlCode: "ALREADY_ENROLLED",
|
|
208
|
+
when: "Learner is already enrolled"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
policy: {
|
|
213
|
+
auth: "user"
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
var CompleteLessonContract = defineCommand({
|
|
217
|
+
meta: {
|
|
218
|
+
key: "learning.completeLesson",
|
|
219
|
+
version: "1.0.0",
|
|
220
|
+
stability: "stable",
|
|
221
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
222
|
+
tags: ["learning", "progress"],
|
|
223
|
+
description: "Mark a lesson as completed.",
|
|
224
|
+
goal: "Record lesson completion and earn XP.",
|
|
225
|
+
context: "Called when a learner finishes a lesson."
|
|
226
|
+
},
|
|
227
|
+
io: {
|
|
228
|
+
input: CompleteLessonInput,
|
|
229
|
+
output: SuccessOutput,
|
|
230
|
+
errors: {
|
|
231
|
+
LESSON_NOT_FOUND: {
|
|
232
|
+
description: "Lesson does not exist",
|
|
233
|
+
http: 404,
|
|
234
|
+
gqlCode: "LESSON_NOT_FOUND",
|
|
235
|
+
when: "Lesson ID is invalid"
|
|
236
|
+
},
|
|
237
|
+
NOT_ENROLLED: {
|
|
238
|
+
description: "Not enrolled in course",
|
|
239
|
+
http: 403,
|
|
240
|
+
gqlCode: "NOT_ENROLLED",
|
|
241
|
+
when: "Learner is not enrolled in the course"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
policy: {
|
|
246
|
+
auth: "user"
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
var SubmitCardReviewContract = defineCommand({
|
|
250
|
+
meta: {
|
|
251
|
+
key: "learning.submitCardReview",
|
|
252
|
+
version: "1.0.0",
|
|
253
|
+
stability: "stable",
|
|
254
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
255
|
+
tags: ["learning", "flashcards"],
|
|
256
|
+
description: "Submit a flashcard review.",
|
|
257
|
+
goal: "Record review and update SRS schedule.",
|
|
258
|
+
context: "Called when reviewing flashcards."
|
|
259
|
+
},
|
|
260
|
+
io: {
|
|
261
|
+
input: SubmitCardReviewInput,
|
|
262
|
+
output: SuccessOutput,
|
|
263
|
+
errors: {
|
|
264
|
+
CARD_NOT_FOUND: {
|
|
265
|
+
description: "Card does not exist",
|
|
266
|
+
http: 404,
|
|
267
|
+
gqlCode: "CARD_NOT_FOUND",
|
|
268
|
+
when: "Card ID is invalid"
|
|
269
|
+
},
|
|
270
|
+
INVALID_RATING: {
|
|
271
|
+
description: "Invalid rating",
|
|
272
|
+
http: 400,
|
|
273
|
+
gqlCode: "INVALID_RATING",
|
|
274
|
+
when: "Rating must be AGAIN, HARD, GOOD, or EASY"
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
policy: {
|
|
279
|
+
auth: "user"
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
var GetDueCardsContract = defineQuery({
|
|
283
|
+
meta: {
|
|
284
|
+
key: "learning.getDueCards",
|
|
285
|
+
version: "1.0.0",
|
|
286
|
+
stability: "stable",
|
|
287
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
288
|
+
tags: ["learning", "flashcards"],
|
|
289
|
+
description: "Get flashcards due for review.",
|
|
290
|
+
goal: "Get the next batch of cards to review.",
|
|
291
|
+
context: "Called when starting a review session."
|
|
292
|
+
},
|
|
293
|
+
io: {
|
|
294
|
+
input: GetDueCardsInput,
|
|
295
|
+
output: GetDueCardsOutput
|
|
296
|
+
},
|
|
297
|
+
policy: {
|
|
298
|
+
auth: "user"
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
var GetLearnerDashboardContract = defineQuery({
|
|
302
|
+
meta: {
|
|
303
|
+
key: "learning.getDashboard",
|
|
304
|
+
version: "1.0.0",
|
|
305
|
+
stability: "stable",
|
|
306
|
+
owners: [...LEARNING_JOURNEY_OWNERS],
|
|
307
|
+
tags: ["learning", "dashboard"],
|
|
308
|
+
description: "Get learner dashboard data.",
|
|
309
|
+
goal: "Display learner progress and stats.",
|
|
310
|
+
context: "Called when viewing the learning dashboard."
|
|
311
|
+
},
|
|
312
|
+
io: {
|
|
313
|
+
input: GetLearnerDashboardInput,
|
|
314
|
+
output: LearnerDashboardModel
|
|
315
|
+
},
|
|
316
|
+
policy: {
|
|
317
|
+
auth: "user"
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
export {
|
|
321
|
+
SubmitCardReviewContract,
|
|
322
|
+
GetLearnerDashboardContract,
|
|
323
|
+
GetDueCardsContract,
|
|
324
|
+
EnrollInCourseContract,
|
|
325
|
+
CompleteLessonContract
|
|
326
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// src/docs/learning-journey.docblock.ts
|
|
2
|
+
import { registerDocBlocks } from "@contractspec/lib.contracts/docs";
|
|
3
|
+
var learningJourneyDocBlocks = [
|
|
4
|
+
{
|
|
5
|
+
id: "docs.learning-journey.engine",
|
|
6
|
+
title: "Learning Journey Engine",
|
|
7
|
+
summary: "Tracks learners, tracks/modules/steps, progress, quizzes, streaks, XP, and AI coaching hooks for product-integrated onboarding.",
|
|
8
|
+
kind: "reference",
|
|
9
|
+
visibility: "public",
|
|
10
|
+
route: "/docs/learning-journey/engine",
|
|
11
|
+
tags: ["learning", "onboarding", "journey", "education"],
|
|
12
|
+
body: `## Capabilities
|
|
13
|
+
|
|
14
|
+
- **Entities**: Learner, Track, Module, Step, Progress, Quiz, Flashcard, AI Coach, Gamification (XP, streaks, badges).
|
|
15
|
+
- **Contracts**: enroll/resume/advance steps, complete quizzes, record streaks, assign XP, fetch progress dashboards, onboarding list/progress/recordEvent.
|
|
16
|
+
- **Engines**: spaced-repetition (SRS), streak calculator, XP progression.
|
|
17
|
+
- **Events**: learner.enrolled, step.completed, quiz.scored, streak.reset, xp.awarded, onboarding.started/completed/step_completed.
|
|
18
|
+
|
|
19
|
+
## Completion conditions
|
|
20
|
+
- Event-based: name/version/source + payload filter
|
|
21
|
+
- Count-based: require N events (optional time window)
|
|
22
|
+
- Time-bounded: must complete within a window; steps can unlock by day/hour
|
|
23
|
+
- SRS mastery: complete when cards/skills hit mastery thresholds (with required counts)
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
1) Compose schema
|
|
28
|
+
- Include \`learningJourneySchemaContribution\` (entities export) in composition.
|
|
29
|
+
|
|
30
|
+
2) Register contracts/events
|
|
31
|
+
- Import from \`@contractspec/module.learning-journey\` into your spec registry.
|
|
32
|
+
|
|
33
|
+
3) Bind to product actions
|
|
34
|
+
- Tie \`Step\` completion conditions to domain events (e.g., deal.created, agent.run.completed, drill.session.completed).
|
|
35
|
+
- Trigger notifications via Notification Center and audits on completion.
|
|
36
|
+
|
|
37
|
+
4) Gamification
|
|
38
|
+
- Use \`XP\` and \`Streak\` engines to update learner stats; emit analytics for UI.
|
|
39
|
+
|
|
40
|
+
## Example
|
|
41
|
+
|
|
42
|
+
${"```"}ts
|
|
43
|
+
import { learningJourneyEntities } from '@contractspec/module.learning-journey';
|
|
44
|
+
import { StreakEngine } from '@contractspec/module.learning-journey/engines';
|
|
45
|
+
|
|
46
|
+
const streak = new StreakEngine({ graceDays: 1 });
|
|
47
|
+
const updated = streak.compute({ lastActiveAt: new Date(), today: new Date() });
|
|
48
|
+
${"```"},
|
|
49
|
+
|
|
50
|
+
## Guardrails
|
|
51
|
+
|
|
52
|
+
- Keep steps bound to real product events, not just button clicks.
|
|
53
|
+
- Avoid storing PII in content; keep org/user scoping for multi-tenant isolation.
|
|
54
|
+
- Emit analytics and audit logs for completions; respect \`prefers-reduced-motion\` in UIs consuming these specs.
|
|
55
|
+
- Track completion bonuses: \`completionXpBonus\`, \`completionBadgeKey\`, optional \`streakHoursWindow\` + \`streakBonusXp\`.
|
|
56
|
+
`
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "docs.learning-journey.goal",
|
|
60
|
+
title: "Learning Journey — Goal",
|
|
61
|
+
summary: "Why the learning journey engine exists and the outcomes it targets.",
|
|
62
|
+
kind: "goal",
|
|
63
|
+
visibility: "public",
|
|
64
|
+
route: "/docs/learning-journey/goal",
|
|
65
|
+
tags: ["learning", "goal"],
|
|
66
|
+
body: `## Why it matters
|
|
67
|
+
- Provides a regenerable onboarding/education engine tied to product signals.
|
|
68
|
+
- Keeps tracks, steps, quizzes, and gamification consistent across surfaces.
|
|
69
|
+
|
|
70
|
+
## Business/Product goal
|
|
71
|
+
- Drive activation and retention with measurable progress, SRS, and streaks.
|
|
72
|
+
- Allow product teams to adjust journeys safely via specs.
|
|
73
|
+
|
|
74
|
+
## Success criteria
|
|
75
|
+
- Journey changes regenerate UI/API/events without drift.
|
|
76
|
+
- Analytics/audit hooks exist for completions and streaks.`
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "docs.learning-journey.usage",
|
|
80
|
+
title: "Learning Journey — Usage",
|
|
81
|
+
summary: "How to compose, bind, and regenerate journeys safely.",
|
|
82
|
+
kind: "usage",
|
|
83
|
+
visibility: "public",
|
|
84
|
+
route: "/docs/learning-journey/usage",
|
|
85
|
+
tags: ["learning", "usage"],
|
|
86
|
+
body: `## Setup
|
|
87
|
+
1) Include \`learningJourneyEntities\` in schema composition.
|
|
88
|
+
2) Register contracts/events from \`@contractspec/module.learning-journey\`.
|
|
89
|
+
3) Bind steps to real product events (e.g., deal.created, run.completed).
|
|
90
|
+
|
|
91
|
+
## Extend & regenerate
|
|
92
|
+
1) Update track/module/step definitions or quiz schemas in spec.
|
|
93
|
+
2) Regenerate to sync UI/API/events; mark PII paths where needed.
|
|
94
|
+
3) Use Feature Flags to trial new tracks or streak rules.
|
|
95
|
+
|
|
96
|
+
## Guardrails
|
|
97
|
+
- Avoid hardcoded progression; keep engines declarative.
|
|
98
|
+
- Emit analytics/audit for completions; respect user locale/accessibility in presentations.
|
|
99
|
+
- Keep content free of PII; scope learners by org/tenant.`
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "docs.learning-journey.constraints",
|
|
103
|
+
title: "Learning Journey — Constraints & Safety",
|
|
104
|
+
summary: "Internal guardrails for progression, telemetry, and regeneration semantics.",
|
|
105
|
+
kind: "reference",
|
|
106
|
+
visibility: "internal",
|
|
107
|
+
route: "/docs/learning-journey/constraints",
|
|
108
|
+
tags: ["learning", "constraints", "internal"],
|
|
109
|
+
body: `## Constraints
|
|
110
|
+
- Progression (tracks/modules/steps) and engines (SRS, streaks, XP) must stay declarative in spec.
|
|
111
|
+
- Events to emit: learner.enrolled, step.completed, quiz.scored, streak.reset, xp.awarded.
|
|
112
|
+
- Regeneration should not change scoring/streak rules without explicit spec change.
|
|
113
|
+
|
|
114
|
+
## PII & Telemetry
|
|
115
|
+
- Mark PII (learner identifiers) and redact in presentations; keep telemetry aggregated when possible.
|
|
116
|
+
- Respect accessibility (prefers-reduced-motion) in UIs consuming these specs.
|
|
117
|
+
|
|
118
|
+
## Verification
|
|
119
|
+
- Add fixtures for streak/XP rule changes and quiz scoring.
|
|
120
|
+
- Ensure Notifications/Audit wiring persists for completions; analytics emitted for progress.
|
|
121
|
+
- Use Feature Flags to trial new tracks or reward rules; default safe/off.`
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
registerDocBlocks(learningJourneyDocBlocks);
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// src/docs/learning-journey.docblock.ts
|
|
2
|
+
import { registerDocBlocks } from "@contractspec/lib.contracts/docs";
|
|
3
|
+
var learningJourneyDocBlocks = [
|
|
4
|
+
{
|
|
5
|
+
id: "docs.learning-journey.engine",
|
|
6
|
+
title: "Learning Journey Engine",
|
|
7
|
+
summary: "Tracks learners, tracks/modules/steps, progress, quizzes, streaks, XP, and AI coaching hooks for product-integrated onboarding.",
|
|
8
|
+
kind: "reference",
|
|
9
|
+
visibility: "public",
|
|
10
|
+
route: "/docs/learning-journey/engine",
|
|
11
|
+
tags: ["learning", "onboarding", "journey", "education"],
|
|
12
|
+
body: `## Capabilities
|
|
13
|
+
|
|
14
|
+
- **Entities**: Learner, Track, Module, Step, Progress, Quiz, Flashcard, AI Coach, Gamification (XP, streaks, badges).
|
|
15
|
+
- **Contracts**: enroll/resume/advance steps, complete quizzes, record streaks, assign XP, fetch progress dashboards, onboarding list/progress/recordEvent.
|
|
16
|
+
- **Engines**: spaced-repetition (SRS), streak calculator, XP progression.
|
|
17
|
+
- **Events**: learner.enrolled, step.completed, quiz.scored, streak.reset, xp.awarded, onboarding.started/completed/step_completed.
|
|
18
|
+
|
|
19
|
+
## Completion conditions
|
|
20
|
+
- Event-based: name/version/source + payload filter
|
|
21
|
+
- Count-based: require N events (optional time window)
|
|
22
|
+
- Time-bounded: must complete within a window; steps can unlock by day/hour
|
|
23
|
+
- SRS mastery: complete when cards/skills hit mastery thresholds (with required counts)
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
1) Compose schema
|
|
28
|
+
- Include \`learningJourneySchemaContribution\` (entities export) in composition.
|
|
29
|
+
|
|
30
|
+
2) Register contracts/events
|
|
31
|
+
- Import from \`@contractspec/module.learning-journey\` into your spec registry.
|
|
32
|
+
|
|
33
|
+
3) Bind to product actions
|
|
34
|
+
- Tie \`Step\` completion conditions to domain events (e.g., deal.created, agent.run.completed, drill.session.completed).
|
|
35
|
+
- Trigger notifications via Notification Center and audits on completion.
|
|
36
|
+
|
|
37
|
+
4) Gamification
|
|
38
|
+
- Use \`XP\` and \`Streak\` engines to update learner stats; emit analytics for UI.
|
|
39
|
+
|
|
40
|
+
## Example
|
|
41
|
+
|
|
42
|
+
${"```"}ts
|
|
43
|
+
import { learningJourneyEntities } from '@contractspec/module.learning-journey';
|
|
44
|
+
import { StreakEngine } from '@contractspec/module.learning-journey/engines';
|
|
45
|
+
|
|
46
|
+
const streak = new StreakEngine({ graceDays: 1 });
|
|
47
|
+
const updated = streak.compute({ lastActiveAt: new Date(), today: new Date() });
|
|
48
|
+
${"```"},
|
|
49
|
+
|
|
50
|
+
## Guardrails
|
|
51
|
+
|
|
52
|
+
- Keep steps bound to real product events, not just button clicks.
|
|
53
|
+
- Avoid storing PII in content; keep org/user scoping for multi-tenant isolation.
|
|
54
|
+
- Emit analytics and audit logs for completions; respect \`prefers-reduced-motion\` in UIs consuming these specs.
|
|
55
|
+
- Track completion bonuses: \`completionXpBonus\`, \`completionBadgeKey\`, optional \`streakHoursWindow\` + \`streakBonusXp\`.
|
|
56
|
+
`
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "docs.learning-journey.goal",
|
|
60
|
+
title: "Learning Journey — Goal",
|
|
61
|
+
summary: "Why the learning journey engine exists and the outcomes it targets.",
|
|
62
|
+
kind: "goal",
|
|
63
|
+
visibility: "public",
|
|
64
|
+
route: "/docs/learning-journey/goal",
|
|
65
|
+
tags: ["learning", "goal"],
|
|
66
|
+
body: `## Why it matters
|
|
67
|
+
- Provides a regenerable onboarding/education engine tied to product signals.
|
|
68
|
+
- Keeps tracks, steps, quizzes, and gamification consistent across surfaces.
|
|
69
|
+
|
|
70
|
+
## Business/Product goal
|
|
71
|
+
- Drive activation and retention with measurable progress, SRS, and streaks.
|
|
72
|
+
- Allow product teams to adjust journeys safely via specs.
|
|
73
|
+
|
|
74
|
+
## Success criteria
|
|
75
|
+
- Journey changes regenerate UI/API/events without drift.
|
|
76
|
+
- Analytics/audit hooks exist for completions and streaks.`
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "docs.learning-journey.usage",
|
|
80
|
+
title: "Learning Journey — Usage",
|
|
81
|
+
summary: "How to compose, bind, and regenerate journeys safely.",
|
|
82
|
+
kind: "usage",
|
|
83
|
+
visibility: "public",
|
|
84
|
+
route: "/docs/learning-journey/usage",
|
|
85
|
+
tags: ["learning", "usage"],
|
|
86
|
+
body: `## Setup
|
|
87
|
+
1) Include \`learningJourneyEntities\` in schema composition.
|
|
88
|
+
2) Register contracts/events from \`@contractspec/module.learning-journey\`.
|
|
89
|
+
3) Bind steps to real product events (e.g., deal.created, run.completed).
|
|
90
|
+
|
|
91
|
+
## Extend & regenerate
|
|
92
|
+
1) Update track/module/step definitions or quiz schemas in spec.
|
|
93
|
+
2) Regenerate to sync UI/API/events; mark PII paths where needed.
|
|
94
|
+
3) Use Feature Flags to trial new tracks or streak rules.
|
|
95
|
+
|
|
96
|
+
## Guardrails
|
|
97
|
+
- Avoid hardcoded progression; keep engines declarative.
|
|
98
|
+
- Emit analytics/audit for completions; respect user locale/accessibility in presentations.
|
|
99
|
+
- Keep content free of PII; scope learners by org/tenant.`
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "docs.learning-journey.constraints",
|
|
103
|
+
title: "Learning Journey — Constraints & Safety",
|
|
104
|
+
summary: "Internal guardrails for progression, telemetry, and regeneration semantics.",
|
|
105
|
+
kind: "reference",
|
|
106
|
+
visibility: "internal",
|
|
107
|
+
route: "/docs/learning-journey/constraints",
|
|
108
|
+
tags: ["learning", "constraints", "internal"],
|
|
109
|
+
body: `## Constraints
|
|
110
|
+
- Progression (tracks/modules/steps) and engines (SRS, streaks, XP) must stay declarative in spec.
|
|
111
|
+
- Events to emit: learner.enrolled, step.completed, quiz.scored, streak.reset, xp.awarded.
|
|
112
|
+
- Regeneration should not change scoring/streak rules without explicit spec change.
|
|
113
|
+
|
|
114
|
+
## PII & Telemetry
|
|
115
|
+
- Mark PII (learner identifiers) and redact in presentations; keep telemetry aggregated when possible.
|
|
116
|
+
- Respect accessibility (prefers-reduced-motion) in UIs consuming these specs.
|
|
117
|
+
|
|
118
|
+
## Verification
|
|
119
|
+
- Add fixtures for streak/XP rule changes and quiz scoring.
|
|
120
|
+
- Ensure Notifications/Audit wiring persists for completions; analytics emitted for progress.
|
|
121
|
+
- Use Feature Flags to trial new tracks or reward rules; default safe/off.`
|
|
122
|
+
}
|
|
123
|
+
];
|
|
124
|
+
registerDocBlocks(learningJourneyDocBlocks);
|