playcademy 0.29.0 → 0.29.1-beta.1

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/bucket.js CHANGED
@@ -42,7 +42,7 @@ var GAME_API_ROUTES_DIRECTORY = `${GAME_SERVER_ROOT_DIRECTORY}/api`;
42
42
  // ../better-auth/package.json
43
43
  var package_default = {
44
44
  name: "@playcademy/better-auth",
45
- version: "0.0.21",
45
+ version: "0.0.22-beta.1",
46
46
  type: "module",
47
47
  exports: {
48
48
  "./server": {
package/dist/cli.js CHANGED
@@ -1208,7 +1208,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
1208
1208
  // ../better-auth/package.json
1209
1209
  var package_default = {
1210
1210
  name: "@playcademy/better-auth",
1211
- version: "0.0.21",
1211
+ version: "0.0.22-beta.1",
1212
1212
  type: "module",
1213
1213
  exports: {
1214
1214
  "./server": {
@@ -3045,7 +3045,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as re
3045
3045
  import { join as join12 } from "node:path";
3046
3046
 
3047
3047
  // src/version.ts
3048
- var cliVersion = false ? "0.0.0-dev" : "0.29.0";
3048
+ var cliVersion = false ? "0.0.0-dev" : "0.29.1-beta.1";
3049
3049
 
3050
3050
  // src/lib/init/database.ts
3051
3051
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
package/dist/constants.js CHANGED
@@ -21,7 +21,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
21
21
  // ../better-auth/package.json
22
22
  var package_default = {
23
23
  name: "@playcademy/better-auth",
24
- version: "0.0.21",
24
+ version: "0.0.22-beta.1",
25
25
  type: "module",
26
26
  exports: {
27
27
  "./server": {
package/dist/db.js CHANGED
@@ -2333,7 +2333,7 @@ var GAME_API_ROUTES_DIRECTORY = `${GAME_SERVER_ROOT_DIRECTORY}/api`;
2333
2333
  // ../better-auth/package.json
2334
2334
  var package_default = {
2335
2335
  name: "@playcademy/better-auth",
2336
- version: "0.0.21",
2336
+ version: "0.0.22-beta.1",
2337
2337
  type: "module",
2338
2338
  exports: {
2339
2339
  "./server": {
package/dist/index.js CHANGED
@@ -2345,7 +2345,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
2345
2345
  // ../better-auth/package.json
2346
2346
  var package_default = {
2347
2347
  name: "@playcademy/better-auth",
2348
- version: "0.0.21",
2348
+ version: "0.0.22-beta.1",
2349
2349
  type: "module",
2350
2350
  exports: {
2351
2351
  "./server": {
@@ -6486,7 +6486,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync2, readFileSync as re
6486
6486
  import { join as join12 } from "node:path";
6487
6487
 
6488
6488
  // src/version.ts
6489
- var cliVersion = false ? "0.0.0-dev" : "0.29.0";
6489
+ var cliVersion = false ? "0.0.0-dev" : "0.29.1-beta.1";
6490
6490
 
6491
6491
  // src/lib/init/database.ts
6492
6492
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
@@ -22714,6 +22714,10 @@ var SubmitAssessmentBodySchema = external_exports.object({
22714
22714
  message: "Session timing needs a UUID runId and resumeId with non-negative active and inactive seconds"
22715
22715
  }).optional()
22716
22716
  });
22717
+ var FinalizeAssessmentBodySchema = external_exports.object({
22718
+ submissionId: external_exports.string().trim().min(1),
22719
+ xpAwarded: external_exports.number().finite().nonnegative()
22720
+ });
22717
22721
  var StartRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.and(StartAssessmentBodySchema);
22718
22722
  var SaveRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.extend(SaveAssessmentBodySchema.shape);
22719
22723
  var SubmitAssessmentItemRuntimeRequestSchema = AssessmentRuntimeIdentitySchema.extend(SubmitAssessmentItemBodySchema.shape);
@@ -22721,6 +22725,10 @@ var SubmitRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.exten
22721
22725
  appName: external_exports.string().trim().min(1),
22722
22726
  sensorUrl: external_exports.string().url()
22723
22727
  });
22728
+ var FinalizeRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.extend(FinalizeAssessmentBodySchema.shape).extend({
22729
+ appName: external_exports.string().trim().min(1),
22730
+ sensorUrl: external_exports.string().url()
22731
+ });
22724
22732
 
22725
22733
  // src/lib/timeback/assessment-fixtures.ts
22726
22734
  function assessmentFixturePath(workspace = getWorkspace()) {
@@ -1,7 +1,7 @@
1
1
  {
2
- "cliVersion": "0.29.0",
3
- "sdkVersion": "0.17.0",
4
- "runtimeBuildId": "8d696801888c",
5
- "inputFingerprint": "8d696801888c6ba351bc7c899ba3124cdb00864c28c9be0c4fa94eb86f279079",
2
+ "cliVersion": "0.29.1-beta.1",
3
+ "sdkVersion": "0.17.1-beta.1",
4
+ "runtimeBuildId": "a5e840d095cf",
5
+ "inputFingerprint": "a5e840d095cfbc0885ce3cf472f66e1ae5a9bd090739aecaf0b97eecea110752",
6
6
  "entry": "index.js"
7
7
  }
@@ -10058,12 +10058,27 @@ function isAssessmentAttemptOpen(attempt) {
10058
10058
  function isAssessmentAttemptCompleted(attempt) {
10059
10059
  return attempt.inProgress === ASSESSMENT_ATTEMPT_COMPLETED.inProgress && attempt.scoreStatus === ASSESSMENT_ATTEMPT_COMPLETED.scoreStatus;
10060
10060
  }
10061
+ function isAssessmentAttemptAwaitingAward(attempt) {
10062
+ return attempt.inProgress === ASSESSMENT_ATTEMPT_AWAITING_AWARD.inProgress && attempt.scoreStatus === ASSESSMENT_ATTEMPT_AWAITING_AWARD.scoreStatus;
10063
+ }
10061
10064
  function classifyAssessmentSubmission(attempt, submissionId) {
10062
- if (isAssessmentAttemptCompleted(attempt)) {
10065
+ if (isAssessmentAttemptAwaitingAward(attempt)) {
10063
10066
  return attempt.submissionId === submissionId ? "replay" : "reject";
10064
10067
  }
10068
+ if (isAssessmentAttemptCompleted(attempt)) {
10069
+ return "reject";
10070
+ }
10065
10071
  return isAssessmentAttemptOpen(attempt) ? "submit" : "reject";
10066
10072
  }
10073
+ function classifyAssessmentFinalization(attempt, input) {
10074
+ if (isAssessmentAttemptCompleted(attempt)) {
10075
+ return attempt.submissionId === input.submissionId && attempt.xpAwarded === input.xpAwarded ? "replay" : "conflict";
10076
+ }
10077
+ if (!isAssessmentAttemptAwaitingAward(attempt) || attempt.submissionId !== input.submissionId) {
10078
+ return "reject";
10079
+ }
10080
+ return "finalize";
10081
+ }
10067
10082
  function assessmentFlowViolation(message2, details) {
10068
10083
  return {
10069
10084
  code: "ASSESSMENT_FLOW_VIOLATION",
@@ -10092,6 +10107,13 @@ function assessmentAlreadySubmitted(attemptId) {
10092
10107
  details: { attemptId }
10093
10108
  };
10094
10109
  }
10110
+ function assessmentAwardConflict(details) {
10111
+ return {
10112
+ code: "ASSESSMENT_FLOW_VIOLATION",
10113
+ message: "This assessment award conflicts with the recorded finalization.",
10114
+ details
10115
+ };
10116
+ }
10095
10117
  function assessmentResponseVersionConflict(expectedResponseVersion, responseVersion) {
10096
10118
  return {
10097
10119
  code: "RESPONSE_VERSION_CONFLICT",
@@ -11352,7 +11374,7 @@ function orderRuntimeAssessmentTests(tests) {
11352
11374
  return [...tests].toSorted(compareAssessmentCatalogOrder);
11353
11375
  }
11354
11376
  function selectRuntimeAssessment(liveTests, attempts) {
11355
- const resumable = attempts.filter((attempt) => attempt.resumable !== false && isAssessmentAttemptOpen(attempt)).toSorted((left, right) => newestAttempt(left, right, "updatedAt"));
11377
+ const resumable = attempts.filter((attempt) => attempt.resumable !== false && (isAssessmentAttemptOpen(attempt) || isAssessmentAttemptAwaitingAward(attempt))).toSorted((left, right) => newestAttempt(left, right, "updatedAt"));
11356
11378
  if (resumable.length > 0) {
11357
11379
  return {
11358
11380
  kind: "resume",
@@ -11365,7 +11387,7 @@ function selectRuntimeAssessment(liveTests, attempts) {
11365
11387
  return null;
11366
11388
  }
11367
11389
  const completed = attempts.filter(isAssessmentAttemptCompleted);
11368
- const exposedAssessmentKeys = new Set(attempts.filter((attempt) => isAssessmentAttemptOpen(attempt) || isAssessmentAttemptCompleted(attempt)).map((attempt) => attempt.selectedAssessmentKey));
11390
+ const exposedAssessmentKeys = new Set(attempts.filter((attempt) => isAssessmentAttemptOpen(attempt) || isAssessmentAttemptAwaitingAward(attempt) || isAssessmentAttemptCompleted(attempt)).map((attempt) => attempt.selectedAssessmentKey));
11369
11391
  const unattempted = orderedTests.find((test) => !exposedAssessmentKeys.has(test.assessmentKey));
11370
11392
  if (unattempted) {
11371
11393
  return { kind: "start", test: unattempted, reason: "unattempted" };
@@ -11927,7 +11949,7 @@ function masteryStandardMatcher(requested) {
11927
11949
  return canonicalAuthored !== null && assessmentStandardRefKey(canonicalAuthored) === requestedKey;
11928
11950
  };
11929
11951
  }
11930
- var SCRIPT_SCHEMES, DATA_RASTER_IMAGE_PATTERN, metadataSymbol, parser, SUPPORTED_QTI_INTERACTION_TYPES, INTERACTION_TYPES, BLANK_SENTINEL, MARKED_BLANK_PATTERN, MARKED_BLANK_GLOBAL_PATTERN, MATCH_CORRECT_TEMPLATE, MAP_RESPONSE_TEMPLATE, MAP_RESPONSE_TEMPLATES, RESPONSE_PROCESSING_TEMPLATES, COMMON_CORE_MATH_FRAMEWORK_ALIASES, COMMON_CORE_ELA_FRAMEWORK_ALIASES, COMMON_CORE_FRAMEWORK_ALIASES, ASSESSMENT_ATTEMPT_OPEN, ASSESSMENT_ATTEMPT_COMPLETED, ASSESSMENT_RUNTIME_ERROR_STATUS, ROUTING_KEY_MAX_LENGTH, ROUTING_RESULT_KEY_MAX_LENGTH, ROUTING_STAGE_LIMIT, ROUTING_TRACK_LIMIT, ROUTING_NODE_LIMIT, ROUTING_TERMINAL_LIMIT, ROUTING_GROUP_LIMIT, ROUTING_PREDICATE_DEPTH_LIMIT, ROUTING_EXPLORATION_STATE_LIMIT, RoutingKeySchema, RoutingResultKeySchema, DiagnosticTrackOutcomeSchema, DiagnosticActivationPredicateSchema, DiagnosticRoutingTransitionSchema, DiagnosticRoutingManifestV1Schema, GRADE_VALUES, POINT_RESPONSE_PATTERN, REVIEW_SELECTION_POLICY_VERSION, DEFAULT_REVIEW_SELECTION_POLICY, ASSESSMENT_RUNTIME_FIXTURE_BUNDLE_VERSION, RuntimeSubjectSchema, RuntimeGradeSchema, OptionalQueryGradeSchema, AssessmentResponseValueSchema, AssessmentRuntimeIdentitySchema, ResponseKeySchema, StartAssessmentBaseSchema, AssessmentStandardRefSchema, LatestAssessmentFilterBaseSchema, LatestAssessmentFiltersSchema, LatestRuntimeAssessmentQuerySchema, StartAssessmentBodySchema, SaveAssessmentBodySchema, SubmitAssessmentItemBodySchema, SubmitAssessmentBodySchema, StartRuntimeAssessmentRequestSchema, SaveRuntimeAssessmentRequestSchema, SubmitAssessmentItemRuntimeRequestSchema, SubmitRuntimeAssessmentRequestSchema;
11952
+ var SCRIPT_SCHEMES, DATA_RASTER_IMAGE_PATTERN, metadataSymbol, parser, SUPPORTED_QTI_INTERACTION_TYPES, INTERACTION_TYPES, BLANK_SENTINEL, MARKED_BLANK_PATTERN, MARKED_BLANK_GLOBAL_PATTERN, MATCH_CORRECT_TEMPLATE, MAP_RESPONSE_TEMPLATE, MAP_RESPONSE_TEMPLATES, RESPONSE_PROCESSING_TEMPLATES, COMMON_CORE_MATH_FRAMEWORK_ALIASES, COMMON_CORE_ELA_FRAMEWORK_ALIASES, COMMON_CORE_FRAMEWORK_ALIASES, ASSESSMENT_ATTEMPT_OPEN, ASSESSMENT_ATTEMPT_COMPLETED, ASSESSMENT_ATTEMPT_AWAITING_AWARD, ASSESSMENT_RUNTIME_ERROR_STATUS, ROUTING_KEY_MAX_LENGTH, ROUTING_RESULT_KEY_MAX_LENGTH, ROUTING_STAGE_LIMIT, ROUTING_TRACK_LIMIT, ROUTING_NODE_LIMIT, ROUTING_TERMINAL_LIMIT, ROUTING_GROUP_LIMIT, ROUTING_PREDICATE_DEPTH_LIMIT, ROUTING_EXPLORATION_STATE_LIMIT, RoutingKeySchema, RoutingResultKeySchema, DiagnosticTrackOutcomeSchema, DiagnosticActivationPredicateSchema, DiagnosticRoutingTransitionSchema, DiagnosticRoutingManifestV1Schema, GRADE_VALUES, POINT_RESPONSE_PATTERN, REVIEW_SELECTION_POLICY_VERSION, DEFAULT_REVIEW_SELECTION_POLICY, ASSESSMENT_RUNTIME_FIXTURE_BUNDLE_VERSION, RuntimeSubjectSchema, RuntimeGradeSchema, OptionalQueryGradeSchema, AssessmentResponseValueSchema, AssessmentRuntimeIdentitySchema, ResponseKeySchema, StartAssessmentBaseSchema, AssessmentStandardRefSchema, LatestAssessmentFilterBaseSchema, LatestAssessmentFiltersSchema, LatestRuntimeAssessmentQuerySchema, StartAssessmentBodySchema, SaveAssessmentBodySchema, SubmitAssessmentItemBodySchema, SubmitAssessmentBodySchema, FinalizeAssessmentBodySchema, StartRuntimeAssessmentRequestSchema, SaveRuntimeAssessmentRequestSchema, SubmitAssessmentItemRuntimeRequestSchema, SubmitRuntimeAssessmentRequestSchema, FinalizeRuntimeAssessmentRequestSchema;
11931
11953
  var init_assessment_runtime2 = __esm({
11932
11954
  "../timeback/dist/engines/assessment-runtime/index.js"() {
11933
11955
  "use strict";
@@ -12021,6 +12043,10 @@ var init_assessment_runtime2 = __esm({
12021
12043
  inProgress: "false",
12022
12044
  scoreStatus: "fully graded"
12023
12045
  };
12046
+ ASSESSMENT_ATTEMPT_AWAITING_AWARD = {
12047
+ inProgress: "false",
12048
+ scoreStatus: "submitted"
12049
+ };
12024
12050
  ASSESSMENT_RUNTIME_ERROR_STATUS = {
12025
12051
  NO_ELIGIBLE_TESTS: 404,
12026
12052
  REVIEW_BANK_SHORTAGE: 422,
@@ -12187,6 +12213,10 @@ var init_assessment_runtime2 = __esm({
12187
12213
  message: "Session timing needs a UUID runId and resumeId with non-negative active and inactive seconds"
12188
12214
  }).optional()
12189
12215
  });
12216
+ FinalizeAssessmentBodySchema = external_exports.object({
12217
+ submissionId: external_exports.string().trim().min(1),
12218
+ xpAwarded: external_exports.number().finite().nonnegative()
12219
+ });
12190
12220
  StartRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.and(StartAssessmentBodySchema);
12191
12221
  SaveRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.extend(SaveAssessmentBodySchema.shape);
12192
12222
  SubmitAssessmentItemRuntimeRequestSchema = AssessmentRuntimeIdentitySchema.extend(SubmitAssessmentItemBodySchema.shape);
@@ -12194,6 +12224,10 @@ var init_assessment_runtime2 = __esm({
12194
12224
  appName: external_exports.string().trim().min(1),
12195
12225
  sensorUrl: external_exports.string().url()
12196
12226
  });
12227
+ FinalizeRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.extend(FinalizeAssessmentBodySchema.shape).extend({
12228
+ appName: external_exports.string().trim().min(1),
12229
+ sensorUrl: external_exports.string().url()
12230
+ });
12197
12231
  }
12198
12232
  });
12199
12233
 
@@ -12747,7 +12781,7 @@ var init_local_assessment_runtime = __esm({
12747
12781
  const attempt = this.authorize(studentId2, attemptId);
12748
12782
  const submissionDisposition = classifyAssessmentSubmission(attempt, input.submissionId);
12749
12783
  if (submissionDisposition === "replay") {
12750
- return this.completedResult(attempt);
12784
+ return this.submittedResult(attempt);
12751
12785
  }
12752
12786
  if (submissionDisposition === "reject") {
12753
12787
  throw failure(assessmentAlreadySubmitted(attemptId));
@@ -12779,11 +12813,11 @@ var init_local_assessment_runtime = __esm({
12779
12813
  attempt.score = scoreAssessmentFixture(test, attempt.responses);
12780
12814
  }
12781
12815
  attempt.submissionId = input.submissionId;
12782
- attempt.inProgress = ASSESSMENT_ATTEMPT_COMPLETED.inProgress;
12783
- attempt.scoreStatus = ASSESSMENT_ATTEMPT_COMPLETED.scoreStatus;
12816
+ attempt.inProgress = ASSESSMENT_ATTEMPT_AWAITING_AWARD.inProgress;
12817
+ attempt.scoreStatus = ASSESSMENT_ATTEMPT_AWAITING_AWARD.scoreStatus;
12784
12818
  attempt.updatedAt = this.timestamp();
12785
12819
  attempt.scoreDate = attempt.updatedAt;
12786
- return this.completedResult(attempt);
12820
+ return this.submittedResult(attempt);
12787
12821
  }
12788
12822
  finalizeDiagnostic(attempt, submissionId) {
12789
12823
  const diagnostic = this.requireDiagnosticAttempt(attempt);
@@ -12814,11 +12848,36 @@ var init_local_assessment_runtime = __esm({
12814
12848
  }
12815
12849
  attempt.score = aggregateFixtureItemScores(diagnostic.commits.map((commit) => commit.scoring));
12816
12850
  attempt.submissionId = submissionId;
12851
+ attempt.inProgress = ASSESSMENT_ATTEMPT_AWAITING_AWARD.inProgress;
12852
+ attempt.scoreStatus = ASSESSMENT_ATTEMPT_AWAITING_AWARD.scoreStatus;
12853
+ attempt.updatedAt = this.timestamp();
12854
+ attempt.scoreDate = attempt.updatedAt;
12855
+ return this.submittedDiagnosticResult(attempt, tracks);
12856
+ }
12857
+ finalize(studentId2, attemptId, input) {
12858
+ const attempt = this.authorize(studentId2, attemptId);
12859
+ switch (classifyAssessmentFinalization(attempt, input)) {
12860
+ case "replay": {
12861
+ return this.finalizedResult(attempt);
12862
+ }
12863
+ case "conflict": {
12864
+ throw failure(
12865
+ assessmentAwardConflict({
12866
+ attemptId,
12867
+ submissionId: input.submissionId,
12868
+ xpAwarded: input.xpAwarded
12869
+ })
12870
+ );
12871
+ }
12872
+ case "reject": {
12873
+ throw failure(assessmentAlreadySubmitted(attemptId));
12874
+ }
12875
+ }
12876
+ attempt.xpAwarded = input.xpAwarded;
12817
12877
  attempt.inProgress = ASSESSMENT_ATTEMPT_COMPLETED.inProgress;
12818
12878
  attempt.scoreStatus = ASSESSMENT_ATTEMPT_COMPLETED.scoreStatus;
12819
12879
  attempt.updatedAt = this.timestamp();
12820
- attempt.scoreDate = attempt.updatedAt;
12821
- return this.completedDiagnosticResult(attempt, tracks);
12880
+ return this.finalizedResult(attempt);
12822
12881
  }
12823
12882
  catalog(input, studentId2) {
12824
12883
  const requestedReviewFingerprint = input.purpose === "review" ? reviewRequestFingerprint(input, DEFAULT_REVIEW_SELECTION_POLICY) : void 0;
@@ -12846,7 +12905,7 @@ var init_local_assessment_runtime = __esm({
12846
12905
  (attempt) => attempt.studentId === studentId2 && attempt.catalogId === catalog.id && attempt.activityId === input.activityId && (input.purpose !== "review" || attempt.selection.kind === "standards-review" && attempt.review?.requestFingerprint === requestedReviewFingerprint) && (input.purpose !== "mastery" || attempt.selection.kind === "standard-quiz" && masteryStandardMatches(
12847
12906
  attempt.selection.standard,
12848
12907
  input.standard
12849
- )) && (input.purpose !== "diagnostic" || attempt.selection.kind === "platform-routed-diagnostic" && attempt.selection.diagnosticKey === input.diagnosticKey) && isAssessmentAttemptOpen(attempt)
12908
+ )) && (input.purpose !== "diagnostic" || attempt.selection.kind === "platform-routed-diagnostic" && attempt.selection.diagnosticKey === input.diagnosticKey) && (isAssessmentAttemptOpen(attempt) || isAssessmentAttemptAwaitingAward(attempt))
12850
12909
  );
12851
12910
  }
12852
12911
  courses.set(key, entry);
@@ -13010,7 +13069,22 @@ var init_local_assessment_runtime = __esm({
13010
13069
  });
13011
13070
  }
13012
13071
  snapshot(attempt) {
13013
- const completed = isAssessmentAttemptCompleted(attempt);
13072
+ if (isAssessmentAttemptAwaitingAward(attempt)) {
13073
+ return {
13074
+ attemptId: attempt.attemptId,
13075
+ responseVersion: attempt.responseVersion,
13076
+ status: "awaiting_award",
13077
+ result: this.submittedResult(attempt)
13078
+ };
13079
+ }
13080
+ if (isAssessmentAttemptCompleted(attempt)) {
13081
+ return {
13082
+ attemptId: attempt.attemptId,
13083
+ responseVersion: attempt.responseVersion,
13084
+ status: "completed",
13085
+ result: this.finalizedResult(attempt)
13086
+ };
13087
+ }
13014
13088
  const catalog = this.catalogForAttempt(attempt);
13015
13089
  const test = this.testForAttempt(attempt);
13016
13090
  if (attempt.selection.kind === "platform-routed-diagnostic") {
@@ -13027,7 +13101,7 @@ var init_local_assessment_runtime = __esm({
13027
13101
  return {
13028
13102
  attemptId: attempt.attemptId,
13029
13103
  responseVersion: attempt.responseVersion,
13030
- status: completed ? "completed" : "in_progress",
13104
+ status: "in_progress",
13031
13105
  flow: "platform-routed-item-submit",
13032
13106
  activityData: {
13033
13107
  activityId: attempt.activityId,
@@ -13038,13 +13112,13 @@ var init_local_assessment_runtime = __esm({
13038
13112
  assessment: assessmentPresentationForAttempt(test.assessment, attempt.attemptId),
13039
13113
  selection: structuredClone(attempt.selection),
13040
13114
  routing: this.diagnosticRoutingSnapshot(attempt, replayed.state),
13041
- completion: completed ? this.completedResult(attempt) : null
13115
+ completion: null
13042
13116
  };
13043
13117
  }
13044
13118
  return {
13045
13119
  attemptId: attempt.attemptId,
13046
13120
  responseVersion: attempt.responseVersion,
13047
- status: completed ? "completed" : "in_progress",
13121
+ status: "in_progress",
13048
13122
  flow: assessmentFlowForSelection(attempt.selection),
13049
13123
  activityData: {
13050
13124
  activityId: attempt.activityId,
@@ -13057,11 +13131,11 @@ var init_local_assessment_runtime = __esm({
13057
13131
  assessment: assessmentPresentationForAttempt(test.assessment, attempt.attemptId),
13058
13132
  responses: structuredClone(attempt.responses),
13059
13133
  itemSubmissions: structuredClone(attempt.itemSubmissions),
13060
- score: completed ? structuredClone(this.scoreForAttempt(attempt)) : null,
13134
+ score: null,
13061
13135
  selection: structuredClone(attempt.selection)
13062
13136
  };
13063
13137
  }
13064
- completedResult(attempt) {
13138
+ submittedResult(attempt) {
13065
13139
  if (attempt.selection.kind === "platform-routed-diagnostic") {
13066
13140
  const diagnostic = this.requireDiagnosticAttempt(attempt);
13067
13141
  const { routingManifest } = this.diagnosticTestForAttempt(attempt);
@@ -13070,12 +13144,13 @@ var init_local_assessment_runtime = __esm({
13070
13144
  if (!tracks) {
13071
13145
  throw new Error("A completed diagnostic must have terminal track results");
13072
13146
  }
13073
- return this.completedDiagnosticResult(attempt, tracks);
13147
+ return this.submittedDiagnosticResult(attempt, tracks);
13074
13148
  }
13075
13149
  const result = {
13076
13150
  attemptId: attempt.attemptId,
13151
+ submissionId: attempt.submissionId,
13077
13152
  responseVersion: attempt.responseVersion,
13078
- status: "completed",
13153
+ status: "awaiting_award",
13079
13154
  responses: structuredClone(attempt.responses),
13080
13155
  score: structuredClone(this.scoreForAttempt(attempt))
13081
13156
  };
@@ -13090,17 +13165,28 @@ var init_local_assessment_runtime = __esm({
13090
13165
  }
13091
13166
  return { ...result, purpose: attempt.selection.purpose };
13092
13167
  }
13093
- completedDiagnosticResult(attempt, tracks) {
13168
+ submittedDiagnosticResult(attempt, tracks) {
13094
13169
  const diagnostic = this.requireDiagnosticAttempt(attempt);
13095
13170
  return {
13096
13171
  purpose: "diagnostic",
13097
13172
  attemptId: attempt.attemptId,
13173
+ submissionId: attempt.submissionId,
13098
13174
  diagnosticKey: diagnostic.diagnosticKey,
13099
13175
  responseVersion: attempt.responseVersion,
13100
- status: "completed",
13176
+ status: "awaiting_award",
13101
13177
  tracks: structuredClone([...tracks])
13102
13178
  };
13103
13179
  }
13180
+ finalizedResult(attempt) {
13181
+ if (attempt.xpAwarded === void 0) {
13182
+ throw new Error("A completed assessment must have recorded XP");
13183
+ }
13184
+ return {
13185
+ ...this.submittedResult(attempt),
13186
+ status: "completed",
13187
+ xpAwarded: attempt.xpAwarded
13188
+ };
13189
+ }
13104
13190
  diagnosticRoutingSnapshot(attempt, state) {
13105
13191
  const diagnostic = this.requireDiagnosticAttempt(attempt);
13106
13192
  return projectDiagnosticRoutingSnapshot(diagnostic.routingRevision, state);
@@ -13351,6 +13437,7 @@ var init_shared = __esm({
13351
13437
  // ../edge-play/src/game/routes/integrations/timeback/assessment-fixture-runtime.ts
13352
13438
  var assessment_fixture_runtime_exports = {};
13353
13439
  __export(assessment_fixture_runtime_exports, {
13440
+ FINALIZE: () => FINALIZE,
13354
13441
  GET: () => GET2,
13355
13442
  LATEST: () => LATEST,
13356
13443
  SAVE: () => SAVE,
@@ -13422,6 +13509,12 @@ async function SUBMIT(c) {
13422
13509
  return provider(c).submit(studentId(c), c.req.param("attemptId"), input);
13423
13510
  });
13424
13511
  }
13512
+ async function FINALIZE(c) {
13513
+ return respond(c, RESPOND_ERROR, async () => {
13514
+ const input = parseBody2(FinalizeAssessmentBodySchema, await c.req.json());
13515
+ return provider(c).finalize(studentId(c), c.req.param("attemptId"), input);
13516
+ });
13517
+ }
13425
13518
  var fixtureSource, fixtureProvider, RESPOND_ERROR;
13426
13519
  var init_assessment_fixture_runtime = __esm({
13427
13520
  "../edge-play/src/game/routes/integrations/timeback/assessment-fixture-runtime.ts"() {
@@ -13440,6 +13533,7 @@ var init_assessment_fixture_runtime = __esm({
13440
13533
  // ../edge-play/src/game/routes/integrations/timeback/assessment-runtime.ts
13441
13534
  var assessment_runtime_exports = {};
13442
13535
  __export(assessment_runtime_exports, {
13536
+ FINALIZE: () => FINALIZE2,
13443
13537
  GET: () => GET3,
13444
13538
  LATEST: () => LATEST2,
13445
13539
  SAVE: () => SAVE2,
@@ -13519,6 +13613,20 @@ async function SUBMIT2(c) {
13519
13613
  }
13520
13614
  );
13521
13615
  }
13616
+ async function FINALIZE2(c) {
13617
+ return respond(
13618
+ c,
13619
+ { tag: "TimeBack Assessment Finalize", fallback: "Failed to finalize assessment" },
13620
+ async () => {
13621
+ const studentId2 = requireTimebackStudentId(c);
13622
+ assertTimebackIntegrated(c);
13623
+ const input = await c.req.json();
13624
+ return c.get("sdk").timeback.assessments.finalize(studentId2, c.req.param("attemptId"), input, {
13625
+ sensorUrl: new URL(c.req.url).origin
13626
+ });
13627
+ }
13628
+ );
13629
+ }
13522
13630
  var init_assessment_runtime3 = __esm({
13523
13631
  "../edge-play/src/game/routes/integrations/timeback/assessment-runtime.ts"() {
13524
13632
  "use strict";
@@ -13580,9 +13688,9 @@ var init_list = __esm({
13580
13688
  // ../edge-play/src/game/lib/metadata.ts
13581
13689
  function getRuntimeMetadata() {
13582
13690
  return {
13583
- cliVersion: true ? "0.29.0" : "0.0.0-dev",
13584
- sdkVersion: true ? "0.17.0" : "0.0.0-dev",
13585
- buildId: true ? "8d696801888c" : "dev-source"
13691
+ cliVersion: true ? "0.29.1-beta.1" : "0.0.0-dev",
13692
+ sdkVersion: true ? "0.17.1-beta.1" : "0.0.0-dev",
13693
+ buildId: true ? "a5e840d095cf" : "dev-source"
13586
13694
  };
13587
13695
  }
13588
13696
  var init_metadata = __esm({
@@ -15796,6 +15904,17 @@ function createTimebackNamespace(client) {
15796
15904
  appName: client.config.name,
15797
15905
  sensorUrl: context.sensorUrl
15798
15906
  }
15907
+ ),
15908
+ finalize: (studentId2, attemptId, input, context) => client["request"](
15909
+ `/api/timeback/assessments/${encodeURIComponent(attemptId)}/finalize`,
15910
+ "POST",
15911
+ {
15912
+ ...input,
15913
+ gameId: client.gameId,
15914
+ studentId: studentId2,
15915
+ appName: client.config.name,
15916
+ sensorUrl: context.sensorUrl
15917
+ }
15799
15918
  )
15800
15919
  },
15801
15920
  /**
@@ -16656,6 +16775,7 @@ function registerAssessmentRoutes(app, assessments) {
16656
16775
  app.post(`${GAME_ROUTES.TIMEBACK.ASSESSMENTS}/:attemptId/save`, assessments.SAVE);
16657
16776
  app.post(`${GAME_ROUTES.TIMEBACK.ASSESSMENTS}/:attemptId/submit-item`, assessments.SUBMIT_ITEM);
16658
16777
  app.post(`${GAME_ROUTES.TIMEBACK.ASSESSMENTS}/:attemptId/submit`, assessments.SUBMIT);
16778
+ app.post(`${GAME_ROUTES.TIMEBACK.ASSESSMENTS}/:attemptId/finalize`, assessments.FINALIZE);
16659
16779
  }
16660
16780
  async function timebackNotConfiguredStub(c) {
16661
16781
  return c.json({ __playcademyDevWarning: "timeback-not-configured" });
@@ -16767,6 +16887,7 @@ async function registerBuiltinRoutes(app, integrations, hasAssessmentFixtures =
16767
16887
  app.post(`${assessmentsBase}/:attemptId/save`, timebackNotConfiguredStub);
16768
16888
  app.post(`${assessmentsBase}/:attemptId/submit-item`, timebackNotConfiguredStub);
16769
16889
  app.post(`${assessmentsBase}/:attemptId/submit`, timebackNotConfiguredStub);
16890
+ app.post(`${assessmentsBase}/:attemptId/finalize`, timebackNotConfiguredStub);
16770
16891
  }
16771
16892
  }
16772
16893
  if (assessments) {
@@ -1,7 +1,7 @@
1
1
  {
2
- "cliVersion": "0.29.0",
3
- "sdkVersion": "0.17.0",
4
- "runtimeBuildId": "8d696801888c",
5
- "inputFingerprint": "8d696801888c6ba351bc7c899ba3124cdb00864c28c9be0c4fa94eb86f279079",
2
+ "cliVersion": "0.29.1-beta.1",
3
+ "sdkVersion": "0.17.1-beta.1",
4
+ "runtimeBuildId": "a5e840d095cf",
5
+ "inputFingerprint": "a5e840d095cfbc0885ce3cf472f66e1ae5a9bd090739aecaf0b97eecea110752",
6
6
  "entry": "index.js"
7
7
  }
package/dist/utils.js CHANGED
@@ -396,7 +396,7 @@ var DASHBOARD_API_ROUTES_DIRECTORY = "api";
396
396
  // ../better-auth/package.json
397
397
  var package_default = {
398
398
  name: "@playcademy/better-auth",
399
- version: "0.0.21",
399
+ version: "0.0.22-beta.1",
400
400
  type: "module",
401
401
  exports: {
402
402
  "./server": {
@@ -2849,7 +2849,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync2, writeFileSync as wr
2849
2849
  import { dirname as dirname4, join as join13 } from "node:path";
2850
2850
 
2851
2851
  // src/version.ts
2852
- var cliVersion = false ? "0.0.0-dev" : "0.29.0";
2852
+ var cliVersion = false ? "0.0.0-dev" : "0.29.1-beta.1";
2853
2853
 
2854
2854
  // src/lib/build/binary-resource.ts
2855
2855
  function writeFileTree(baseDir, files) {
@@ -15482,6 +15482,10 @@ var SubmitAssessmentBodySchema = external_exports.object({
15482
15482
  message: "Session timing needs a UUID runId and resumeId with non-negative active and inactive seconds"
15483
15483
  }).optional()
15484
15484
  });
15485
+ var FinalizeAssessmentBodySchema = external_exports.object({
15486
+ submissionId: external_exports.string().trim().min(1),
15487
+ xpAwarded: external_exports.number().finite().nonnegative()
15488
+ });
15485
15489
  var StartRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.and(StartAssessmentBodySchema);
15486
15490
  var SaveRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.extend(SaveAssessmentBodySchema.shape);
15487
15491
  var SubmitAssessmentItemRuntimeRequestSchema = AssessmentRuntimeIdentitySchema.extend(SubmitAssessmentItemBodySchema.shape);
@@ -15489,6 +15493,10 @@ var SubmitRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.exten
15489
15493
  appName: external_exports.string().trim().min(1),
15490
15494
  sensorUrl: external_exports.string().url()
15491
15495
  });
15496
+ var FinalizeRuntimeAssessmentRequestSchema = AssessmentRuntimeIdentitySchema.extend(FinalizeAssessmentBodySchema.shape).extend({
15497
+ appName: external_exports.string().trim().min(1),
15498
+ sensorUrl: external_exports.string().url()
15499
+ });
15492
15500
 
15493
15501
  // src/lib/timeback/assessment-fixtures.ts
15494
15502
  function assessmentFixturePath(workspace = getWorkspace()) {
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __pcCreateRequire } from 'node:module'; const require = __pcCreateRequire(import.meta.url);
2
2
 
3
3
  // src/version.ts
4
- var cliVersion = false ? "0.0.0-dev" : "0.29.0";
4
+ var cliVersion = false ? "0.0.0-dev" : "0.29.1-beta.1";
5
5
  export {
6
6
  cliVersion
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playcademy",
3
- "version": "0.29.0",
3
+ "version": "0.29.1-beta.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "@inquirer/prompts": "^7.8.6",
58
- "@playcademy/sdk": "0.17.0",
58
+ "@playcademy/sdk": "0.17.1-beta.1",
59
59
  "chokidar": "^4.0.3",
60
60
  "colorette": "^2.0.20",
61
61
  "commander": "^14.0.1",