@vue-skuilder/standalone-ui 0.2.5 → 0.2.7

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.
@@ -24632,6 +24632,8 @@ var init_v4 = __esmMin((() => {
24632
24632
  ContentNavigator: () => ContentNavigator,
24633
24633
  CouchDBToStaticPacker: () => CouchDBToStaticPacker,
24634
24634
  CourseLookup: () => CourseLookup,
24635
+ DIVERSITY_FLOOR: () => DIVERSITY_FLOOR,
24636
+ DIVERSITY_STRENGTH: () => DIVERSITY_STRENGTH,
24635
24637
  DocType: () => DocType,
24636
24638
  DocTypePrefixes: () => DocTypePrefixes,
24637
24639
  ENV: () => ENV,
@@ -24657,6 +24659,7 @@ var init_v4 = __esmMin((() => {
24657
24659
  computeSpread: () => computeSpread,
24658
24660
  computeStrategyGradient: () => computeStrategyGradient,
24659
24661
  createOrchestrationContext: () => createOrchestrationContext,
24662
+ diversityRerank: () => diversityRerank,
24660
24663
  docIsDeleted: () => docIsDeleted,
24661
24664
  endSessionTracking: () => endSessionTracking,
24662
24665
  ensureAppDataDirectory: () => ensureAppDataDirectory,
@@ -24911,6 +24914,47 @@ function getCourseDB(t) {
24911
24914
  let c = `coursedb-${t}`;
24912
24915
  return new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + c, createPouchDBConfig());
24913
24916
  }
24917
+ function diversityRerank(t, c = {}) {
24918
+ let u = c.strength ?? DIVERSITY_STRENGTH, d = c.floor ?? DIVERSITY_FLOOR, m = t.length;
24919
+ if (m <= 1) return t;
24920
+ let g = /* @__PURE__ */ new Map();
24921
+ for (let c of t) for (let t of c.tags ?? []) g.set(t, (g.get(t) ?? 0) + 1);
24922
+ let b = /* @__PURE__ */ new Map();
24923
+ for (let [t, c] of g) b.set(t, Math.log(m / c));
24924
+ let S = [...t], C = /* @__PURE__ */ new Map(), w = [], repetitionLoad = (t) => {
24925
+ let c = 0;
24926
+ for (let u of t.tags ?? []) {
24927
+ let t = C.get(u);
24928
+ t && (c += (b.get(u) ?? 0) * t);
24929
+ }
24930
+ return c;
24931
+ };
24932
+ for (; S.length > 0;) {
24933
+ let t = 0, c = -Infinity, m = 1, g = 0;
24934
+ for (let b = 0; b < S.length; b++) {
24935
+ let C = S[b], w = repetitionLoad(C), T = w > 0 ? Math.max(d, 1 / (1 + u * w)) : 1, E = C.score * T;
24936
+ E > c && (c = E, t = b, m = T, g = w);
24937
+ }
24938
+ let [b] = S.splice(t, 1);
24939
+ if (Number.isFinite(b.score) && m < 1) {
24940
+ let t = b.score * m;
24941
+ w.push({
24942
+ ...b,
24943
+ score: t,
24944
+ provenance: [...b.provenance, {
24945
+ strategy: STRATEGY,
24946
+ strategyId: STRATEGY_ID,
24947
+ strategyName: STRATEGY_NAME,
24948
+ action: "penalized",
24949
+ score: t,
24950
+ reason: `repeated tags (load ${g.toFixed(2)}) \u2192 \xD7${m.toFixed(2)}`
24951
+ }]
24952
+ });
24953
+ } else w.push(b);
24954
+ for (let t of b.tags ?? []) C.set(t, (C.get(t) ?? 0) + 1);
24955
+ }
24956
+ return w;
24957
+ }
24914
24958
  function registerPipelineForDebug(t) {
24915
24959
  _activePipeline = t;
24916
24960
  }
@@ -25510,7 +25554,7 @@ function logResultCards(t) {
25510
25554
  if (!(!VERBOSE_RESULTS || t.length === 0)) {
25511
25555
  logger.info(`[Pipeline] Results (${t.length} cards):`);
25512
25556
  for (let c = 0; c < t.length; c++) {
25513
- let u = t[c], d = u.tags?.slice(0, 3).join(", ") || "", m = u.provenance.filter((t) => t.strategy === "hierarchyDefinition" || t.strategy === "priorityDefinition" || t.strategy === "interferenceFilter" || t.strategy === "letterGating" || t.strategy === "ephemeralHint").map((t) => {
25557
+ let u = t[c], d = u.tags?.slice(0, 3).join(", ") || "", m = u.provenance.filter((t) => t.strategy === "hierarchyDefinition" || t.strategy === "priorityDefinition" || t.strategy === "interferenceFilter" || t.strategy === "letterGating" || t.strategy === "ephemeralHint" || t.strategy === "diversityRerank").map((t) => {
25514
25558
  let c = t.action === "boosted" ? "↑" : t.action === "penalized" ? "↓" : "=";
25515
25559
  return `${t.strategyName}${c}${t.score.toFixed(2)}`;
25516
25560
  }).join(" | ");
@@ -26743,7 +26787,7 @@ function mountSessionDebugger() {
26743
26787
  let t = window;
26744
26788
  t.skuilder = t.skuilder || {}, t.skuilder.session = sessionDebugAPI;
26745
26789
  }
26746
- var import___vite_browser_external, import___vite_browser_external$1, import___vite_browser_external$2, import_browser_ponyfill, import_browser_ponyfill$1, import_browser, _SessionController2, __defProp, __getOwnPropNames, __glob, __esm, __export, init_adminDB, init_classroomDB, init_SyncStrategy, isDevelopment, logger, init_logger, GuestUsername, log, DocType, DocTypePrefixes, init_types_legacy, init_util, pouchdb_setup_default, init_pouchdb_setup, init_dataDirectory, REVIEW_TIME_FORMAT, log2, init_userDBHelpers, Loggable, init_Loggable, UpdateQueue, init_updateQueue, UsrCrsData, init_user_course_relDB, CLIENT_CACHE, init_clientCache, AlreadyTaggedErr, init_courseAPI, courseLookupDBTitle, CourseLookup, init_courseLookupDB, PipelineDebugger_exports, _activePipeline, MAX_RUNS, runHistory, DISCARDED_KEEP_TOP, _uiContainer, _selectedRunIndex, _cardSearchQuery, pipelineDebugAPI, init_PipelineDebugger, CompositeGenerator_exports, AggregationMode, DEFAULT_AGGREGATION_MODE, FREQUENCY_BOOST_FACTOR, CompositeGenerator, init_CompositeGenerator, elo_exports, ELO_RELEVANCE_SIGMA, ELONavigator, init_elo, generators_exports, init_generators, prescribed_exports, DEFAULT_FRESHNESS_WINDOW, DEFAULT_MAX_DIRECT_PER_RUN, DEFAULT_MAX_SUPPORT_PER_RUN, DEFAULT_HIERARCHY_DEPTH, DEFAULT_MIN_COUNT, BASE_TARGET_SCORE, BASE_SUPPORT_SCORE, DISCOVERED_SUPPORT_SCORE, MAX_TARGET_MULTIPLIER, MAX_SUPPORT_MULTIPLIER, PRESCRIBED_DEBUG_VERSION, PrescribedCardsGenerator, init_prescribed, srs_exports, DEFAULT_HEALTHY_BACKLOG, MAX_BACKLOG_PRESSURE, SRSNavigator, init_srs, types_exports, init_types, globImport_generators, init_, DEFAULT_LEARNABLE_WEIGHT, init_contentNavigationStrategy, WeightedFilter_exports, WeightedFilter, init_WeightedFilter, eloDistance_exports, DEFAULT_HALF_LIFE, DEFAULT_MIN_MULTIPLIER, DEFAULT_MAX_MULTIPLIER, init_eloDistance, hierarchyDefinition_exports, DEFAULT_MIN_COUNT2, HierarchyDefinitionNavigator, init_hierarchyDefinition, userTagPreference_exports, UserTagPreferenceFilter, init_userTagPreference, filters_exports, init_filters, inferredPreferenceStub_exports, INFERRED_PREFERENCE_NAVIGATOR_STUB, init_inferredPreferenceStub, interferenceMitigator_exports, DEFAULT_MIN_COUNT3, DEFAULT_MIN_ELAPSED_DAYS, DEFAULT_INTERFERENCE_DECAY, InterferenceMitigatorNavigator, init_interferenceMitigator, relativePriority_exports, DEFAULT_PRIORITY, DEFAULT_PRIORITY_INFLUENCE, DEFAULT_COMBINE_MODE, RelativePriorityNavigator, init_relativePriority, types_exports2, init_types2, userGoalStub_exports, USER_GOAL_NAVIGATOR_STUB, init_userGoalStub, globImport_filters, init_2, init_gradient, MIN_OBSERVATIONS_FOR_UPDATE, LEARNING_RATE, MAX_WEIGHT_DELTA, MIN_R_SQUARED_FOR_GRADIENT, FLAT_GRADIENT_THRESHOLD, MAX_HISTORY_LENGTH, init_learning, init_signal, init_recording, MIN_SPREAD, MAX_SPREAD, MIN_WEIGHT, MAX_WEIGHT, init_orchestration, Pipeline_exports, VERBOSE_RESULTS, Pipeline, init_Pipeline, defaults_exports, init_defaults, PipelineAssembler_exports, PipelineAssembler, init_PipelineAssembler, globImport, init_3, navigators_exports, navigatorRegistry, Navigators, NavigatorRole, NavigatorRoles, ContentNavigator, init_navigators, CoursesDB, CourseDB, init_courseDB, classroomLookupDBTitle, CLASSROOM_CONFIG, ClassroomDBBase, StudentClassroomDB, TeacherClassroomDB, ClassroomLookupDB, init_classroomDB2, AdminDB, init_adminDB2, CourseSyncService_exports, DEFAULT_REPLICATION, CourseSyncService, init_CourseSyncService, init_auth, CouchDBSyncStrategy_exports, log3, CouchDBSyncStrategy, init_CouchDBSyncStrategy, isBrowser, GUEST_LOCAL_DB, localUserDB, pouchDBincludeCredentialsConfig, REVIEW_TIME_FORMAT2, init_couch, log4, BaseUser, userCoursesDoc, userClassroomsDoc, init_BaseUserDB, init_common, PouchDataLayerProvider_exports, CouchDataLayerProvider, init_PouchDataLayerProvider, pathUtils, nodeFS, StaticDataUnpacker, init_StaticDataUnpacker, StaticCourseDB, init_courseDB2, StaticCoursesDB, init_coursesDB, NoOpSyncStrategy, init_NoOpSyncStrategy, StaticDataLayerProvider_exports, StaticDataLayerProvider, init_StaticDataLayerProvider, NOT_SET, ENV, dataLayerInstance, init_factory, TagFilteredContentSource, init_TagFilteredContentSource, init_contentSource, init_courseDB3, init_dataLayerProvider, init_userDB, init_interfaces, init_user, init_strategyState, init_userOutcome, init_cardProcessor, init_types3, init_bulkImport, userDBDebugAPI, init_UserDBDebugger, init_core, duration, SrsService, EloService, ResponseProcessor, CardHydrationService, ItemQueue, CouchDBToStaticPacker, DEFAULT_MIGRATION_OPTIONS, FileSystemError, nodeFS2, nodeFS3, nodePath, StaticToCouchDBMigrator, QuotaRoundRobinMixer, MAX_RUNS2, runHistory2, mixerDebugAPI, activeController, OVERLAY_ID, POLL_MS, INLINE_THRESHOLD, SPINNER_FRAMES, spinnerFrame, overlayEl, pollHandle, lastSnapshot, copyFlashUntil, minified, expanded, activeSession, sessionHistory, MAX_HISTORY, sessionDebugAPI, SessionController, init_dist = __esmMin((() => {
26790
+ var import___vite_browser_external, import___vite_browser_external$1, import___vite_browser_external$2, import_browser_ponyfill, import_browser_ponyfill$1, import_browser, _SessionController2, __defProp, __getOwnPropNames, __glob, __esm, __export, init_adminDB, init_classroomDB, init_SyncStrategy, isDevelopment, logger, init_logger, GuestUsername, log, DocType, DocTypePrefixes, init_types_legacy, init_util, pouchdb_setup_default, init_pouchdb_setup, init_dataDirectory, REVIEW_TIME_FORMAT, log2, init_userDBHelpers, Loggable, init_Loggable, UpdateQueue, init_updateQueue, UsrCrsData, init_user_course_relDB, CLIENT_CACHE, init_clientCache, AlreadyTaggedErr, init_courseAPI, courseLookupDBTitle, CourseLookup, init_courseLookupDB, diversityRerank_exports, DIVERSITY_STRENGTH, DIVERSITY_FLOOR, STRATEGY, STRATEGY_ID, STRATEGY_NAME, init_diversityRerank, PipelineDebugger_exports, _activePipeline, MAX_RUNS, runHistory, DISCARDED_KEEP_TOP, _uiContainer, _selectedRunIndex, _cardSearchQuery, pipelineDebugAPI, init_PipelineDebugger, CompositeGenerator_exports, AggregationMode, DEFAULT_AGGREGATION_MODE, FREQUENCY_BOOST_FACTOR, CompositeGenerator, init_CompositeGenerator, elo_exports, ELO_RELEVANCE_SIGMA, ELONavigator, init_elo, generators_exports, init_generators, prescribed_exports, DEFAULT_FRESHNESS_WINDOW, DEFAULT_MAX_DIRECT_PER_RUN, DEFAULT_MAX_SUPPORT_PER_RUN, DEFAULT_HIERARCHY_DEPTH, DEFAULT_MIN_COUNT, DEFAULT_PRACTICE_MIN_COUNT, DEFAULT_MAX_PRACTICE_PER_RUN, BASE_TARGET_SCORE, BASE_SUPPORT_SCORE, DISCOVERED_SUPPORT_SCORE, BASE_PRACTICE_SCORE, MAX_TARGET_MULTIPLIER, MAX_SUPPORT_MULTIPLIER, PRESCRIBED_DEBUG_VERSION, PrescribedCardsGenerator, init_prescribed, srs_exports, DEFAULT_HEALTHY_BACKLOG, MAX_BACKLOG_PRESSURE, SRSNavigator, init_srs, types_exports, init_types, globImport_generators, init_, DEFAULT_LEARNABLE_WEIGHT, init_contentNavigationStrategy, WeightedFilter_exports, WeightedFilter, init_WeightedFilter, eloDistance_exports, DEFAULT_HALF_LIFE, DEFAULT_MIN_MULTIPLIER, DEFAULT_MAX_MULTIPLIER, init_eloDistance, hierarchyDefinition_exports, DEFAULT_MIN_COUNT2, HierarchyDefinitionNavigator, init_hierarchyDefinition, userTagPreference_exports, UserTagPreferenceFilter, init_userTagPreference, filters_exports, init_filters, inferredPreferenceStub_exports, INFERRED_PREFERENCE_NAVIGATOR_STUB, init_inferredPreferenceStub, interferenceMitigator_exports, DEFAULT_MIN_COUNT3, DEFAULT_MIN_ELAPSED_DAYS, DEFAULT_INTERFERENCE_DECAY, InterferenceMitigatorNavigator, init_interferenceMitigator, relativePriority_exports, DEFAULT_PRIORITY, DEFAULT_PRIORITY_INFLUENCE, DEFAULT_COMBINE_MODE, RelativePriorityNavigator, init_relativePriority, types_exports2, init_types2, userGoalStub_exports, USER_GOAL_NAVIGATOR_STUB, init_userGoalStub, globImport_filters, init_2, init_gradient, MIN_OBSERVATIONS_FOR_UPDATE, LEARNING_RATE, MAX_WEIGHT_DELTA, MIN_R_SQUARED_FOR_GRADIENT, FLAT_GRADIENT_THRESHOLD, MAX_HISTORY_LENGTH, init_learning, init_signal, init_recording, MIN_SPREAD, MAX_SPREAD, MIN_WEIGHT, MAX_WEIGHT, init_orchestration, Pipeline_exports, VERBOSE_RESULTS, Pipeline, init_Pipeline, defaults_exports, init_defaults, PipelineAssembler_exports, PipelineAssembler, init_PipelineAssembler, globImport, init_3, navigators_exports, navigatorRegistry, Navigators, NavigatorRole, NavigatorRoles, ContentNavigator, init_navigators, CoursesDB, CourseDB, init_courseDB, classroomLookupDBTitle, CLASSROOM_CONFIG, ClassroomDBBase, StudentClassroomDB, TeacherClassroomDB, ClassroomLookupDB, init_classroomDB2, AdminDB, init_adminDB2, CourseSyncService_exports, DEFAULT_REPLICATION, CourseSyncService, init_CourseSyncService, init_auth, CouchDBSyncStrategy_exports, log3, CouchDBSyncStrategy, init_CouchDBSyncStrategy, isBrowser, GUEST_LOCAL_DB, localUserDB, pouchDBincludeCredentialsConfig, REVIEW_TIME_FORMAT2, init_couch, log4, BaseUser, userCoursesDoc, userClassroomsDoc, init_BaseUserDB, init_common, PouchDataLayerProvider_exports, CouchDataLayerProvider, init_PouchDataLayerProvider, pathUtils, nodeFS, StaticDataUnpacker, init_StaticDataUnpacker, StaticCourseDB, init_courseDB2, StaticCoursesDB, init_coursesDB, NoOpSyncStrategy, init_NoOpSyncStrategy, StaticDataLayerProvider_exports, StaticDataLayerProvider, init_StaticDataLayerProvider, NOT_SET, ENV, dataLayerInstance, init_factory, TagFilteredContentSource, init_TagFilteredContentSource, init_contentSource, init_courseDB3, init_dataLayerProvider, init_userDB, init_interfaces, init_user, init_strategyState, init_userOutcome, init_cardProcessor, init_types3, init_bulkImport, userDBDebugAPI, init_UserDBDebugger, init_core, duration, SrsService, EloService, ResponseProcessor, CardHydrationService, ItemQueue, CouchDBToStaticPacker, DEFAULT_MIGRATION_OPTIONS, FileSystemError, nodeFS2, nodeFS3, nodePath, StaticToCouchDBMigrator, QuotaRoundRobinMixer, MAX_RUNS2, runHistory2, mixerDebugAPI, activeController, OVERLAY_ID, POLL_MS, INLINE_THRESHOLD, SPINNER_FRAMES, spinnerFrame, overlayEl, pollHandle, lastSnapshot, copyFlashUntil, minified, expanded, activeSession, sessionHistory, MAX_HISTORY, sessionDebugAPI, SessionController, init_dist = __esmMin((() => {
26747
26791
  init_defineProperty(), init_index_browser_es$5(), init_index_browser_es(), init_index_es(), import___vite_browser_external = /* @__PURE__ */ __toESM$2(require___vite_browser_external(), 1), import___vite_browser_external$1 = /* @__PURE__ */ __toESM$2(require___vite_browser_external(), 1), import___vite_browser_external$2 = /* @__PURE__ */ __toESM$2(require___vite_browser_external(), 1), init_moment(), init_dist$1(), init_esm_browser(), import_browser_ponyfill = /* @__PURE__ */ __toESM$2(require_browser_ponyfill(), 1), import_browser_ponyfill$1 = /* @__PURE__ */ __toESM$2(require_browser_ponyfill(), 1), import_browser = /* @__PURE__ */ __toESM$2(require_browser(), 1), __defProp = Object.defineProperty, __getOwnPropNames = Object.getOwnPropertyNames, __glob = (t) => (c) => {
26748
26792
  var u = t[c];
26749
26793
  if (u) return u();
@@ -26943,6 +26987,12 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
26943
26987
  }
26944
26988
  }
26945
26989
  }, _defineProperty$2(t, "_dbInstance", null), t);
26990
+ } }), diversityRerank_exports = {}, __export(diversityRerank_exports, {
26991
+ DIVERSITY_FLOOR: () => DIVERSITY_FLOOR,
26992
+ DIVERSITY_STRENGTH: () => DIVERSITY_STRENGTH,
26993
+ diversityRerank: () => diversityRerank
26994
+ }), init_diversityRerank = __esm({ "src/core/navigators/diversityRerank.ts"() {
26995
+ DIVERSITY_STRENGTH = .6, DIVERSITY_FLOOR = .3, STRATEGY = "diversityRerank", STRATEGY_ID = "DIVERSITY_RERANK", STRATEGY_NAME = "Diversity Re-rank";
26946
26996
  } }), PipelineDebugger_exports = {}, __export(PipelineDebugger_exports, {
26947
26997
  buildRunReport: () => buildRunReport,
26948
26998
  captureRun: () => captureRun,
@@ -27298,7 +27348,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27298
27348
  }
27299
27349
  };
27300
27350
  } }), generators_exports = {}, init_generators = __esm({ "src/core/navigators/generators/index.ts"() {} }), prescribed_exports = {}, __export(prescribed_exports, { default: () => PrescribedCardsGenerator }), init_prescribed = __esm({ "src/core/navigators/generators/prescribed.ts"() {
27301
- init_navigators(), init_logger(), DEFAULT_FRESHNESS_WINDOW = 3, DEFAULT_MAX_DIRECT_PER_RUN = 3, DEFAULT_MAX_SUPPORT_PER_RUN = 3, DEFAULT_HIERARCHY_DEPTH = 2, DEFAULT_MIN_COUNT = 3, BASE_TARGET_SCORE = 1, BASE_SUPPORT_SCORE = .8, DISCOVERED_SUPPORT_SCORE = 12, MAX_TARGET_MULTIPLIER = 8, MAX_SUPPORT_MULTIPLIER = 4, PRESCRIBED_DEBUG_VERSION = "testversion-prescribed-v3", PrescribedCardsGenerator = class extends ContentNavigator {
27351
+ init_navigators(), init_logger(), DEFAULT_FRESHNESS_WINDOW = 3, DEFAULT_MAX_DIRECT_PER_RUN = 3, DEFAULT_MAX_SUPPORT_PER_RUN = 3, DEFAULT_HIERARCHY_DEPTH = 2, DEFAULT_MIN_COUNT = 3, DEFAULT_PRACTICE_MIN_COUNT = 3, DEFAULT_MAX_PRACTICE_PER_RUN = 4, BASE_TARGET_SCORE = 1, BASE_SUPPORT_SCORE = .8, DISCOVERED_SUPPORT_SCORE = 12, BASE_PRACTICE_SCORE = 1, MAX_TARGET_MULTIPLIER = 8, MAX_SUPPORT_MULTIPLIER = 4, PRESCRIBED_DEBUG_VERSION = "testversion-prescribed-v3", PrescribedCardsGenerator = class extends ContentNavigator {
27302
27352
  constructor(t, c, u) {
27303
27353
  super(t, c, u), _defineProperty$2(this, "name", void 0), _defineProperty$2(this, "config", void 0), this.name = u.name || "Prescribed Cards", this.config = this.parseConfig(u.serializedData), logger.debug(`[Prescribed] Initialized with ${this.config.groups.length} groups and ${this.config.groups.reduce((t, c) => t + c.targetCardIds.length, 0)} targets`);
27304
27354
  }
@@ -27336,8 +27386,18 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27336
27386
  userGlobalElo: T
27337
27387
  });
27338
27388
  Fr.push(c), logger.info(`[Prescribed] Group '${t.id}': ${t.targetCardIds.length} targets total, ${c.encounteredTargets.size} encountered, ${c.pendingTargets.length} pending (${c.surfaceableTargets.length} surfaceable, ${c.blockedTargets.length} blocked), ${c.supportCandidates.length} authored support candidates, ${c.discoveredSupportCandidates.length} discovered support candidates, pressure=${c.pressureMultiplier.toFixed(2)}`), c.blockedTargets.length > 0 && (logger.info(`[Prescribed] Group '${t.id}' blocked targets: ${c.blockedTargets.join(", ")}`), logger.info(`[Prescribed] Group '${t.id}' support tags needed: ${c.supportTags.join(", ") || "(none)"}`), logger.info(`[Prescribed] Group '${t.id}' escalation mode: ` + (c.supportCandidates.length > 0 ? "direct-support" : c.discoveredSupportCandidates.length > 0 ? "inserted-support-candidates" : "boost-only")), c.discoveredSupportCandidates.length > 0 && logger.info(`[Prescribed] Group '${t.id}' discovered support candidates: ${c.discoveredSupportCandidates.join(", ")}`)), Mr.groups[t.id] = this.buildNextGroupState(c, S.groups[t.id]);
27339
- let d = this.buildDirectTargetCards(c, u, Pr), g = this.buildSupportCards(c, u, Pr), w = this.buildDiscoveredSupportCards(c, u, Pr);
27340
- Nr.push(...d, ...g, ...w);
27389
+ let d = this.buildDirectTargetCards(c, u, Pr), g = this.buildSupportCards(c, u, Pr), w = this.buildDiscoveredSupportCards(c, u, Pr), D = this.buildPracticeCards({
27390
+ group: t,
27391
+ courseId: u,
27392
+ emittedIds: Pr,
27393
+ cardsByTag: jr,
27394
+ hierarchyConfigs: C,
27395
+ userTagElo: E,
27396
+ userGlobalElo: T,
27397
+ activeIds: m,
27398
+ seenIds: b
27399
+ });
27400
+ Nr.push(...d, ...g, ...w, ...D);
27341
27401
  }
27342
27402
  let Ir = this.buildSupportHintSummary(Fr), Lr = Object.keys(Ir.boostTags).length > 0 ? {
27343
27403
  boostTags: Ir.boostTags,
@@ -27355,7 +27415,9 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27355
27415
  } : { cards: [] };
27356
27416
  let Rr = pickTopByScore(Nr, t), zr = /* @__PURE__ */ new Map();
27357
27417
  for (let t of Rr) {
27358
- let c = t.provenance[0], u = c?.reason.match(/group=([^;]+)/)?.[1], d = c?.reason.includes("mode=support") ? "supportIds" : "targetIds";
27418
+ let c = t.provenance[0];
27419
+ if (c?.reason.includes("mode=practice")) continue;
27420
+ let u = c?.reason.match(/group=([^;]+)/)?.[1], d = c?.reason.includes("mode=support") ? "supportIds" : "targetIds";
27359
27421
  u && (zr.has(u) || zr.set(u, {
27360
27422
  targetIds: [],
27361
27423
  supportIds: []
@@ -27399,7 +27461,10 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27399
27461
  enabled: t.hierarchyWalk?.enabled !== !1,
27400
27462
  maxDepth: typeof t.hierarchyWalk?.maxDepth == "number" ? t.hierarchyWalk.maxDepth : DEFAULT_HIERARCHY_DEPTH
27401
27463
  },
27402
- retireOnEncounter: t.retireOnEncounter !== !1
27464
+ retireOnEncounter: t.retireOnEncounter !== !1,
27465
+ practiceTagPatterns: dedupe(Array.isArray(t.practiceTagPatterns) ? t.practiceTagPatterns.filter((t) => typeof t == "string") : []),
27466
+ practiceMinCount: typeof t.practiceMinCount == "number" ? t.practiceMinCount : DEFAULT_PRACTICE_MIN_COUNT,
27467
+ maxPracticeCardsPerRun: typeof t.maxPracticeCardsPerRun == "number" ? t.maxPracticeCardsPerRun : DEFAULT_MAX_PRACTICE_PER_RUN
27403
27468
  })).filter((t) => t.targetCardIds.length > 0) };
27404
27469
  } catch {
27405
27470
  return { groups: [] };
@@ -27527,6 +27592,41 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27527
27592
  });
27528
27593
  return g;
27529
27594
  }
27595
+ buildPracticeCards(t) {
27596
+ let { group: c, courseId: u, emittedIds: d, cardsByTag: m, hierarchyConfigs: g, userTagElo: b, userGlobalElo: S, activeIds: C, seenIds: w } = t, T = c.practiceTagPatterns ?? [];
27597
+ if (T.length === 0) return [];
27598
+ let E = c.practiceMinCount ?? DEFAULT_PRACTICE_MIN_COUNT, D = c.maxPracticeCardsPerRun ?? DEFAULT_MAX_PRACTICE_PER_RUN, O = [...m.keys()].filter((t) => T.some((c) => matchesTagPattern(t, c)) && this.isUnlockedGatedSkill(t, g, b, S) && (b[t]?.count ?? 0) < E);
27599
+ if (O.length === 0) return [];
27600
+ let Or = this.findDiscoveredSupportCards({
27601
+ supportTags: O,
27602
+ cardsByTag: m,
27603
+ activeIds: C,
27604
+ seenIds: w,
27605
+ excludedIds: d,
27606
+ limit: D
27607
+ });
27608
+ if (Or.length === 0) return [];
27609
+ logger.info(`[Prescribed] Group '${c.id}' practice: ${O.length} unlocked under-practiced skill(s), emitting ${Or.length} drill card(s)`);
27610
+ let kr = [];
27611
+ for (let t of Or) d.add(t), kr.push({
27612
+ cardId: t,
27613
+ courseId: u,
27614
+ score: BASE_PRACTICE_SCORE,
27615
+ provenance: [{
27616
+ strategy: "prescribed",
27617
+ strategyName: this.strategyName || this.name,
27618
+ strategyId: this.strategyId || "NAVIGATION_STRATEGY-prescribed",
27619
+ action: "generated",
27620
+ score: BASE_PRACTICE_SCORE,
27621
+ reason: `mode=practice;group=${c.id};underPracticedSkills=${O.length};practiceTags=${O.slice(0, 8).join("|")}${O.length > 8 ? "|…" : ""};testversion=${PRESCRIBED_DEBUG_VERSION}`
27622
+ }]
27623
+ });
27624
+ return kr;
27625
+ }
27626
+ isUnlockedGatedSkill(t, c, u, d) {
27627
+ let m = c.map((c) => c.prerequisites[t]).filter((t) => Array.isArray(t) && t.length > 0);
27628
+ return m.length === 0 ? !1 : m.every((t) => t.every((t) => this.isPrerequisiteMet(t, u[t.tag], d)));
27629
+ }
27530
27630
  findSupportCardsByTags(t, c, u) {
27531
27631
  if (u.length === 0) return [];
27532
27632
  let d = t.supportCardIds ?? [], m = t.supportTagPatterns ?? [];
@@ -28106,7 +28206,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28106
28206
  Pipeline: () => Pipeline,
28107
28207
  mergeHints: () => mergeHints2
28108
28208
  }), init_Pipeline = __esm({ "src/core/navigators/Pipeline.ts"() {
28109
- init_navigators(), init_logger(), init_orchestration(), init_PipelineDebugger(), VERBOSE_RESULTS = !0, Pipeline = class extends ContentNavigator {
28209
+ init_navigators(), init_logger(), init_orchestration(), init_PipelineDebugger(), init_diversityRerank(), VERBOSE_RESULTS = !0, Pipeline = class extends ContentNavigator {
28110
28210
  constructor(t, c, u, d) {
28111
28211
  super(), _defineProperty$2(this, "generator", void 0), _defineProperty$2(this, "filters", void 0), _defineProperty$2(this, "_cachedOrchestration", null), _defineProperty$2(this, "_tagCache", /* @__PURE__ */ new Map()), _defineProperty$2(this, "_ephemeralHints", null), this.generator = t, this.filters = c, this.user = u, this.course = d, d.getCourseConfig().then((t) => {
28112
28212
  logger.debug(`[pipeline] Crated pipeline for ${t.name}`);
@@ -28182,7 +28282,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28182
28282
  }
28183
28283
  b = b.filter((t) => t.score > 0);
28184
28284
  let kr = this._ephemeralHints;
28185
- kr && (this._ephemeralHints = null, b = this.applyHints(b, kr, E)), b.sort((t, c) => c.score - t.score);
28285
+ kr && (this._ephemeralHints = null, b = this.applyHints(b, kr, E)), b = diversityRerank(b), b.sort((t, c) => c.score - t.score);
28186
28286
  let Ar = performance.now(), jr = b.slice(0, t);
28187
28287
  logger.info(`[Pipeline:timing] total=${(Ar - c).toFixed(0)}ms (context=${(d - c).toFixed(0)} generate=${(S - d).toFixed(0)} hydrate=${(T - S).toFixed(0)} filter=${(Ar - T).toFixed(0)})`);
28188
28288
  let Mr = jr.slice(0, 3).map((t) => t.score);
@@ -28418,6 +28518,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28418
28518
  "./PipelineAssembler.ts": () => Promise.resolve().then(() => (init_PipelineAssembler(), PipelineAssembler_exports)),
28419
28519
  "./PipelineDebugger.ts": () => Promise.resolve().then(() => (init_PipelineDebugger(), PipelineDebugger_exports)),
28420
28520
  "./defaults.ts": () => Promise.resolve().then(() => (init_defaults(), defaults_exports)),
28521
+ "./diversityRerank.ts": () => Promise.resolve().then(() => (init_diversityRerank(), diversityRerank_exports)),
28421
28522
  "./filters/WeightedFilter.ts": () => Promise.resolve().then(() => (init_WeightedFilter(), WeightedFilter_exports)),
28422
28523
  "./filters/eloDistance.ts": () => Promise.resolve().then(() => (init_eloDistance(), eloDistance_exports)),
28423
28524
  "./filters/hierarchyDefinition.ts": () => Promise.resolve().then(() => (init_hierarchyDefinition(), hierarchyDefinition_exports)),
@@ -28438,9 +28539,12 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28438
28539
  });
28439
28540
  } }), navigators_exports = {}, __export(navigators_exports, {
28440
28541
  ContentNavigator: () => ContentNavigator,
28542
+ DIVERSITY_FLOOR: () => DIVERSITY_FLOOR,
28543
+ DIVERSITY_STRENGTH: () => DIVERSITY_STRENGTH,
28441
28544
  NavigatorRole: () => NavigatorRole,
28442
28545
  NavigatorRoles: () => NavigatorRoles,
28443
28546
  Navigators: () => Navigators,
28547
+ diversityRerank: () => diversityRerank,
28444
28548
  getCardOrigin: () => getCardOrigin,
28445
28549
  getRegisteredNavigator: () => getRegisteredNavigator,
28446
28550
  getRegisteredNavigatorNames: () => getRegisteredNavigatorNames,
@@ -28453,7 +28557,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28453
28557
  pipelineDebugAPI: () => pipelineDebugAPI,
28454
28558
  registerNavigator: () => registerNavigator
28455
28559
  }), init_navigators = __esm({ "src/core/navigators/index.ts"() {
28456
- init_PipelineDebugger(), init_logger(), init_(), init_2(), init_3(), navigatorRegistry = /* @__PURE__ */ new Map(), Navigators = /* @__PURE__ */ ((t) => (t.ELO = "elo", t.SRS = "srs", t.PRESCRIBED = "prescribed", t.HIERARCHY = "hierarchyDefinition", t.INTERFERENCE = "interferenceMitigator", t.RELATIVE_PRIORITY = "relativePriority", t.USER_TAG_PREFERENCE = "userTagPreference", t))(Navigators || {}), NavigatorRole = /* @__PURE__ */ ((t) => (t.GENERATOR = "generator", t.FILTER = "filter", t))(NavigatorRole || {}), NavigatorRoles = {
28560
+ init_diversityRerank(), init_PipelineDebugger(), init_logger(), init_(), init_2(), init_3(), navigatorRegistry = /* @__PURE__ */ new Map(), Navigators = /* @__PURE__ */ ((t) => (t.ELO = "elo", t.SRS = "srs", t.PRESCRIBED = "prescribed", t.HIERARCHY = "hierarchyDefinition", t.INTERFERENCE = "interferenceMitigator", t.RELATIVE_PRIORITY = "relativePriority", t.USER_TAG_PREFERENCE = "userTagPreference", t))(Navigators || {}), NavigatorRole = /* @__PURE__ */ ((t) => (t.GENERATOR = "generator", t.FILTER = "filter", t))(NavigatorRole || {}), NavigatorRoles = {
28457
28561
  elo: "generator",
28458
28562
  srs: "generator",
28459
28563
  prescribed: "generator",
@@ -31109,13 +31213,17 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31109
31213
  this.seenCardIds.includes(t) || (this.seenCardIds.push(t), this.q.push(u));
31110
31214
  }
31111
31215
  }
31112
- mergeToFront(t, c) {
31113
- let u = 0, d = [];
31114
- for (let m of t) {
31115
- let t = c(m);
31116
- this.seenCardIds.includes(t) || (this.seenCardIds.push(t), d.push(m), u++);
31216
+ mergeToFront(t, c, u) {
31217
+ let d = 0, m = [];
31218
+ for (let g of t) {
31219
+ let t = c(g);
31220
+ if (!this.seenCardIds.includes(t)) this.seenCardIds.push(t), m.push(g), d++;
31221
+ else if (u?.has(t)) {
31222
+ let u = this.q.findIndex((u) => c(u) === t);
31223
+ u >= 0 && m.push(...this.q.splice(u, 1));
31224
+ }
31117
31225
  }
31118
- return this.q.unshift(...d), u;
31226
+ return this.q.unshift(...m), d;
31119
31227
  }
31120
31228
  get toString() {
31121
31229
  return `${typeof this.q[0]}:
@@ -32158,9 +32266,9 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32158
32266
  }));
32159
32267
  let C = S.map((t) => this.courseNameCache.get(t)), w = this.mixer instanceof QuotaRoundRobinMixer ? Math.ceil(m * this.sources.length / g.length) : void 0;
32160
32268
  captureMixerRun(this.mixer.constructor.name, g, S, C, m * this.sources.length, w, b);
32161
- let T = b.filter((t) => getCardOrigin(t) === "review").slice(0, this._initialReviewCap), E = b.filter((t) => getCardOrigin(t) === "new" && !this._servedCardIds.has(t.cardId)).slice(0, d);
32269
+ let T = b.filter((t) => getCardOrigin(t) === "review").slice(0, this._initialReviewCap), E = b.filter((t) => getCardOrigin(t) === "new" && !this._servedCardIds.has(t.cardId)), D = E.filter((t) => t.score === Infinity), O = E.filter((t) => t.score !== Infinity), Or = [...D, ...O.slice(0, Math.max(0, d - D.length))], kr = new Set(D.map((t) => t.cardId));
32162
32270
  logger.debug(`[reviews] got ${T.length} reviews from mixer`);
32163
- let D = c ? "Replan content:\n" : "Mixed content session created with:\n";
32271
+ let Ar = c ? "Replan content:\n" : "Mixed content session created with:\n";
32164
32272
  if (!c) for (let t of T) {
32165
32273
  let c = {
32166
32274
  cardID: t.cardId,
@@ -32170,11 +32278,11 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32170
32278
  reviewID: t.reviewID,
32171
32279
  status: "review"
32172
32280
  };
32173
- this.reviewQ.add(c, c.cardID), D += `Review: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32281
+ this.reviewQ.add(c, c.cardID), Ar += `Review: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32174
32282
  `;
32175
32283
  }
32176
- let O = E.filter((t) => t.score >= _SessionController.WELL_INDICATED_SCORE).length, Or = [];
32177
- for (let t of E) {
32284
+ let jr = Or.filter((t) => t.score >= _SessionController.WELL_INDICATED_SCORE).length, Mr = [];
32285
+ for (let t of Or) {
32178
32286
  let c = {
32179
32287
  cardID: t.cardId,
32180
32288
  courseID: t.courseId,
@@ -32182,16 +32290,16 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32182
32290
  contentSourceID: t.courseId,
32183
32291
  status: "new"
32184
32292
  };
32185
- Or.push(c), D += `New: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32293
+ Mr.push(c), Ar += `New: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32186
32294
  `;
32187
32295
  }
32188
32296
  if (u) {
32189
- let t = this.newQ.mergeToFront(Or, (t) => t.cardID);
32190
- D += `Additive merge: ${t} new cards added to front of newQ
32297
+ let t = this.newQ.mergeToFront(Mr, (t) => t.cardID, kr);
32298
+ Ar += `Additive merge: ${t} new cards added to front of newQ
32191
32299
  `;
32192
- } else if (c) this.newQ.replaceAll(Or, (t) => t.cardID);
32193
- else for (let t of Or) this.newQ.add(t, t.cardID);
32194
- return this.log(D), O;
32300
+ } else if (c) this.newQ.replaceAll(Mr, (t) => t.cardID);
32301
+ else for (let t of Mr) this.newQ.add(t, t.cardID);
32302
+ return this.log(Ar), jr;
32195
32303
  }
32196
32304
  _getItemsToHydrate() {
32197
32305
  let t = [], c = 2;