@vue-skuilder/standalone-ui 0.2.5 → 0.2.8

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,9 +24659,11 @@ 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,
24666
+ getActivePipeline: () => getActivePipeline,
24663
24667
  getAppDataDirectory: () => getAppDataDirectory,
24664
24668
  getCardHistoryID: () => getCardHistoryID,
24665
24669
  getCardOrigin: () => getCardOrigin,
@@ -24911,9 +24915,53 @@ function getCourseDB(t) {
24911
24915
  let c = `coursedb-${t}`;
24912
24916
  return new pouchdb_setup_default(ENV.COUCHDB_SERVER_PROTOCOL + "://" + ENV.COUCHDB_SERVER_URL + c, createPouchDBConfig());
24913
24917
  }
24918
+ function diversityRerank(t, c = {}) {
24919
+ let u = c.strength ?? DIVERSITY_STRENGTH, d = c.floor ?? DIVERSITY_FLOOR, m = t.length;
24920
+ if (m <= 1) return t;
24921
+ let g = /* @__PURE__ */ new Map();
24922
+ for (let c of t) for (let t of c.tags ?? []) g.set(t, (g.get(t) ?? 0) + 1);
24923
+ let b = /* @__PURE__ */ new Map();
24924
+ for (let [t, c] of g) b.set(t, Math.log(m / c));
24925
+ let S = [...t], C = /* @__PURE__ */ new Map(), w = [], repetitionLoad = (t) => {
24926
+ let c = 0;
24927
+ for (let u of t.tags ?? []) {
24928
+ let t = C.get(u);
24929
+ t && (c += (b.get(u) ?? 0) * t);
24930
+ }
24931
+ return c;
24932
+ };
24933
+ for (; S.length > 0;) {
24934
+ let t = 0, c = -Infinity, m = 1, g = 0;
24935
+ for (let b = 0; b < S.length; b++) {
24936
+ let C = S[b], w = repetitionLoad(C), T = w > 0 ? Math.max(d, 1 / (1 + u * w)) : 1, E = C.score * T;
24937
+ E > c && (c = E, t = b, m = T, g = w);
24938
+ }
24939
+ let [b] = S.splice(t, 1);
24940
+ if (Number.isFinite(b.score) && m < 1) {
24941
+ let t = b.score * m;
24942
+ w.push({
24943
+ ...b,
24944
+ score: t,
24945
+ provenance: [...b.provenance, {
24946
+ strategy: STRATEGY,
24947
+ strategyId: STRATEGY_ID,
24948
+ strategyName: STRATEGY_NAME,
24949
+ action: "penalized",
24950
+ score: t,
24951
+ reason: `repeated tags (load ${g.toFixed(2)}) \u2192 \xD7${m.toFixed(2)}`
24952
+ }]
24953
+ });
24954
+ } else w.push(b);
24955
+ for (let t of b.tags ?? []) C.set(t, (C.get(t) ?? 0) + 1);
24956
+ }
24957
+ return w;
24958
+ }
24914
24959
  function registerPipelineForDebug(t) {
24915
24960
  _activePipeline = t;
24916
24961
  }
24962
+ function getActivePipeline() {
24963
+ return _activePipeline;
24964
+ }
24917
24965
  function clearRunHistory() {
24918
24966
  runHistory.length = 0;
24919
24967
  }
@@ -25510,7 +25558,7 @@ function logResultCards(t) {
25510
25558
  if (!(!VERBOSE_RESULTS || t.length === 0)) {
25511
25559
  logger.info(`[Pipeline] Results (${t.length} cards):`);
25512
25560
  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) => {
25561
+ 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
25562
  let c = t.action === "boosted" ? "↑" : t.action === "penalized" ? "↓" : "=";
25515
25563
  return `${t.strategyName}${c}${t.score.toFixed(2)}`;
25516
25564
  }).join(" | ");
@@ -26743,7 +26791,7 @@ function mountSessionDebugger() {
26743
26791
  let t = window;
26744
26792
  t.skuilder = t.skuilder || {}, t.skuilder.session = sessionDebugAPI;
26745
26793
  }
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((() => {
26794
+ 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
26795
  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
26796
  var u = t[c];
26749
26797
  if (u) return u();
@@ -26943,10 +26991,17 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
26943
26991
  }
26944
26992
  }
26945
26993
  }, _defineProperty$2(t, "_dbInstance", null), t);
26994
+ } }), diversityRerank_exports = {}, __export(diversityRerank_exports, {
26995
+ DIVERSITY_FLOOR: () => DIVERSITY_FLOOR,
26996
+ DIVERSITY_STRENGTH: () => DIVERSITY_STRENGTH,
26997
+ diversityRerank: () => diversityRerank
26998
+ }), init_diversityRerank = __esm({ "src/core/navigators/diversityRerank.ts"() {
26999
+ DIVERSITY_STRENGTH = .6, DIVERSITY_FLOOR = .3, STRATEGY = "diversityRerank", STRATEGY_ID = "DIVERSITY_RERANK", STRATEGY_NAME = "Diversity Re-rank";
26946
27000
  } }), PipelineDebugger_exports = {}, __export(PipelineDebugger_exports, {
26947
27001
  buildRunReport: () => buildRunReport,
26948
27002
  captureRun: () => captureRun,
26949
27003
  clearRunHistory: () => clearRunHistory,
27004
+ getActivePipeline: () => getActivePipeline,
26950
27005
  mountPipelineDebugger: () => mountPipelineDebugger,
26951
27006
  pipelineDebugAPI: () => pipelineDebugAPI,
26952
27007
  registerPipelineForDebug: () => registerPipelineForDebug
@@ -27298,7 +27353,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27298
27353
  }
27299
27354
  };
27300
27355
  } }), 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 {
27356
+ 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
27357
  constructor(t, c, u) {
27303
27358
  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
27359
  }
@@ -27336,8 +27391,18 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27336
27391
  userGlobalElo: T
27337
27392
  });
27338
27393
  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);
27394
+ let d = this.buildDirectTargetCards(c, u, Pr), g = this.buildSupportCards(c, u, Pr), w = this.buildDiscoveredSupportCards(c, u, Pr), D = this.buildPracticeCards({
27395
+ group: t,
27396
+ courseId: u,
27397
+ emittedIds: Pr,
27398
+ cardsByTag: jr,
27399
+ hierarchyConfigs: C,
27400
+ userTagElo: E,
27401
+ userGlobalElo: T,
27402
+ activeIds: m,
27403
+ seenIds: b
27404
+ });
27405
+ Nr.push(...d, ...g, ...w, ...D);
27341
27406
  }
27342
27407
  let Ir = this.buildSupportHintSummary(Fr), Lr = Object.keys(Ir.boostTags).length > 0 ? {
27343
27408
  boostTags: Ir.boostTags,
@@ -27355,7 +27420,9 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27355
27420
  } : { cards: [] };
27356
27421
  let Rr = pickTopByScore(Nr, t), zr = /* @__PURE__ */ new Map();
27357
27422
  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";
27423
+ let c = t.provenance[0];
27424
+ if (c?.reason.includes("mode=practice")) continue;
27425
+ let u = c?.reason.match(/group=([^;]+)/)?.[1], d = c?.reason.includes("mode=support") ? "supportIds" : "targetIds";
27359
27426
  u && (zr.has(u) || zr.set(u, {
27360
27427
  targetIds: [],
27361
27428
  supportIds: []
@@ -27399,7 +27466,10 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27399
27466
  enabled: t.hierarchyWalk?.enabled !== !1,
27400
27467
  maxDepth: typeof t.hierarchyWalk?.maxDepth == "number" ? t.hierarchyWalk.maxDepth : DEFAULT_HIERARCHY_DEPTH
27401
27468
  },
27402
- retireOnEncounter: t.retireOnEncounter !== !1
27469
+ retireOnEncounter: t.retireOnEncounter !== !1,
27470
+ practiceTagPatterns: dedupe(Array.isArray(t.practiceTagPatterns) ? t.practiceTagPatterns.filter((t) => typeof t == "string") : []),
27471
+ practiceMinCount: typeof t.practiceMinCount == "number" ? t.practiceMinCount : DEFAULT_PRACTICE_MIN_COUNT,
27472
+ maxPracticeCardsPerRun: typeof t.maxPracticeCardsPerRun == "number" ? t.maxPracticeCardsPerRun : DEFAULT_MAX_PRACTICE_PER_RUN
27403
27473
  })).filter((t) => t.targetCardIds.length > 0) };
27404
27474
  } catch {
27405
27475
  return { groups: [] };
@@ -27527,6 +27597,41 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27527
27597
  });
27528
27598
  return g;
27529
27599
  }
27600
+ buildPracticeCards(t) {
27601
+ let { group: c, courseId: u, emittedIds: d, cardsByTag: m, hierarchyConfigs: g, userTagElo: b, userGlobalElo: S, activeIds: C, seenIds: w } = t, T = c.practiceTagPatterns ?? [];
27602
+ if (T.length === 0) return [];
27603
+ 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);
27604
+ if (O.length === 0) return [];
27605
+ let Or = this.findDiscoveredSupportCards({
27606
+ supportTags: O,
27607
+ cardsByTag: m,
27608
+ activeIds: C,
27609
+ seenIds: w,
27610
+ excludedIds: d,
27611
+ limit: D
27612
+ });
27613
+ if (Or.length === 0) return [];
27614
+ logger.info(`[Prescribed] Group '${c.id}' practice: ${O.length} unlocked under-practiced skill(s), emitting ${Or.length} drill card(s)`);
27615
+ let kr = [];
27616
+ for (let t of Or) d.add(t), kr.push({
27617
+ cardId: t,
27618
+ courseId: u,
27619
+ score: BASE_PRACTICE_SCORE,
27620
+ provenance: [{
27621
+ strategy: "prescribed",
27622
+ strategyName: this.strategyName || this.name,
27623
+ strategyId: this.strategyId || "NAVIGATION_STRATEGY-prescribed",
27624
+ action: "generated",
27625
+ score: BASE_PRACTICE_SCORE,
27626
+ reason: `mode=practice;group=${c.id};underPracticedSkills=${O.length};practiceTags=${O.slice(0, 8).join("|")}${O.length > 8 ? "|…" : ""};testversion=${PRESCRIBED_DEBUG_VERSION}`
27627
+ }]
27628
+ });
27629
+ return kr;
27630
+ }
27631
+ isUnlockedGatedSkill(t, c, u, d) {
27632
+ let m = c.map((c) => c.prerequisites[t]).filter((t) => Array.isArray(t) && t.length > 0);
27633
+ return m.length === 0 ? !1 : m.every((t) => t.every((t) => this.isPrerequisiteMet(t, u[t.tag], d)));
27634
+ }
27530
27635
  findSupportCardsByTags(t, c, u) {
27531
27636
  if (u.length === 0) return [];
27532
27637
  let d = t.supportCardIds ?? [], m = t.supportTagPatterns ?? [];
@@ -28106,7 +28211,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28106
28211
  Pipeline: () => Pipeline,
28107
28212
  mergeHints: () => mergeHints2
28108
28213
  }), init_Pipeline = __esm({ "src/core/navigators/Pipeline.ts"() {
28109
- init_navigators(), init_logger(), init_orchestration(), init_PipelineDebugger(), VERBOSE_RESULTS = !0, Pipeline = class extends ContentNavigator {
28214
+ init_navigators(), init_logger(), init_orchestration(), init_PipelineDebugger(), init_diversityRerank(), VERBOSE_RESULTS = !0, Pipeline = class extends ContentNavigator {
28110
28215
  constructor(t, c, u, d) {
28111
28216
  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
28217
  logger.debug(`[pipeline] Crated pipeline for ${t.name}`);
@@ -28182,7 +28287,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28182
28287
  }
28183
28288
  b = b.filter((t) => t.score > 0);
28184
28289
  let kr = this._ephemeralHints;
28185
- kr && (this._ephemeralHints = null, b = this.applyHints(b, kr, E)), b.sort((t, c) => c.score - t.score);
28290
+ kr && (this._ephemeralHints = null, b = this.applyHints(b, kr, E)), b = diversityRerank(b), b.sort((t, c) => c.score - t.score);
28186
28291
  let Ar = performance.now(), jr = b.slice(0, t);
28187
28292
  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
28293
  let Mr = jr.slice(0, 3).map((t) => t.score);
@@ -28314,6 +28419,27 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28314
28419
  };
28315
28420
  return u;
28316
28421
  }
28422
+ async forecast(t) {
28423
+ let c = t?.threshold ?? .1, u = t?.unseenOnly ?? !0, d = this.course.getCourseID(), m = (await this.course.getAllCardIds()).map((t) => ({
28424
+ cardId: t,
28425
+ courseId: d,
28426
+ score: 1,
28427
+ provenance: []
28428
+ }));
28429
+ m = await this.hydrateTags(m);
28430
+ let g = m.slice(), b = await this.buildContext();
28431
+ for (let t of this.filters) m = await t.transform(m, b);
28432
+ if (t?.hints && (m = this.applyHints(m, t.hints, g)), m = m.filter((t) => t.score >= c), u) {
28433
+ let t;
28434
+ try {
28435
+ t = new Set(await this.user.getSeenCards(d));
28436
+ } catch {
28437
+ t = /* @__PURE__ */ new Set();
28438
+ }
28439
+ m = m.filter((c) => !t.has(c.cardId));
28440
+ }
28441
+ return m.sort((t, c) => c.score - t.score), t?.limit ? m.slice(0, t.limit) : m;
28442
+ }
28317
28443
  async diagnoseCardSpace(t) {
28318
28444
  let c = t?.threshold ?? .1, u = performance.now(), d = await this.course.getAllCardIds(), m = d.map((t) => ({
28319
28445
  cardId: t,
@@ -28418,6 +28544,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28418
28544
  "./PipelineAssembler.ts": () => Promise.resolve().then(() => (init_PipelineAssembler(), PipelineAssembler_exports)),
28419
28545
  "./PipelineDebugger.ts": () => Promise.resolve().then(() => (init_PipelineDebugger(), PipelineDebugger_exports)),
28420
28546
  "./defaults.ts": () => Promise.resolve().then(() => (init_defaults(), defaults_exports)),
28547
+ "./diversityRerank.ts": () => Promise.resolve().then(() => (init_diversityRerank(), diversityRerank_exports)),
28421
28548
  "./filters/WeightedFilter.ts": () => Promise.resolve().then(() => (init_WeightedFilter(), WeightedFilter_exports)),
28422
28549
  "./filters/eloDistance.ts": () => Promise.resolve().then(() => (init_eloDistance(), eloDistance_exports)),
28423
28550
  "./filters/hierarchyDefinition.ts": () => Promise.resolve().then(() => (init_hierarchyDefinition(), hierarchyDefinition_exports)),
@@ -28438,9 +28565,13 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28438
28565
  });
28439
28566
  } }), navigators_exports = {}, __export(navigators_exports, {
28440
28567
  ContentNavigator: () => ContentNavigator,
28568
+ DIVERSITY_FLOOR: () => DIVERSITY_FLOOR,
28569
+ DIVERSITY_STRENGTH: () => DIVERSITY_STRENGTH,
28441
28570
  NavigatorRole: () => NavigatorRole,
28442
28571
  NavigatorRoles: () => NavigatorRoles,
28443
28572
  Navigators: () => Navigators,
28573
+ diversityRerank: () => diversityRerank,
28574
+ getActivePipeline: () => getActivePipeline,
28444
28575
  getCardOrigin: () => getCardOrigin,
28445
28576
  getRegisteredNavigator: () => getRegisteredNavigator,
28446
28577
  getRegisteredNavigatorNames: () => getRegisteredNavigatorNames,
@@ -28453,7 +28584,7 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
28453
28584
  pipelineDebugAPI: () => pipelineDebugAPI,
28454
28585
  registerNavigator: () => registerNavigator
28455
28586
  }), 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 = {
28587
+ 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
28588
  elo: "generator",
28458
28589
  srs: "generator",
28459
28590
  prescribed: "generator",
@@ -31109,13 +31240,17 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31109
31240
  this.seenCardIds.includes(t) || (this.seenCardIds.push(t), this.q.push(u));
31110
31241
  }
31111
31242
  }
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++);
31243
+ mergeToFront(t, c, u) {
31244
+ let d = 0, m = [];
31245
+ for (let g of t) {
31246
+ let t = c(g);
31247
+ if (!this.seenCardIds.includes(t)) this.seenCardIds.push(t), m.push(g), d++;
31248
+ else if (u?.has(t)) {
31249
+ let u = this.q.findIndex((u) => c(u) === t);
31250
+ u >= 0 && m.push(...this.q.splice(u, 1));
31251
+ }
31117
31252
  }
31118
- return this.q.unshift(...d), u;
31253
+ return this.q.unshift(...m), d;
31119
31254
  }
31120
31255
  get toString() {
31121
31256
  return `${typeof this.q[0]}:
@@ -32158,9 +32293,9 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32158
32293
  }));
32159
32294
  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
32295
  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);
32296
+ 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
32297
  logger.debug(`[reviews] got ${T.length} reviews from mixer`);
32163
- let D = c ? "Replan content:\n" : "Mixed content session created with:\n";
32298
+ let Ar = c ? "Replan content:\n" : "Mixed content session created with:\n";
32164
32299
  if (!c) for (let t of T) {
32165
32300
  let c = {
32166
32301
  cardID: t.cardId,
@@ -32170,11 +32305,11 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32170
32305
  reviewID: t.reviewID,
32171
32306
  status: "review"
32172
32307
  };
32173
- this.reviewQ.add(c, c.cardID), D += `Review: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32308
+ this.reviewQ.add(c, c.cardID), Ar += `Review: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32174
32309
  `;
32175
32310
  }
32176
- let O = E.filter((t) => t.score >= _SessionController.WELL_INDICATED_SCORE).length, Or = [];
32177
- for (let t of E) {
32311
+ let jr = Or.filter((t) => t.score >= _SessionController.WELL_INDICATED_SCORE).length, Mr = [];
32312
+ for (let t of Or) {
32178
32313
  let c = {
32179
32314
  cardID: t.cardId,
32180
32315
  courseID: t.courseId,
@@ -32182,16 +32317,16 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32182
32317
  contentSourceID: t.courseId,
32183
32318
  status: "new"
32184
32319
  };
32185
- Or.push(c), D += `New: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32320
+ Mr.push(c), Ar += `New: ${t.courseId}::${t.cardId} (score: ${t.score.toFixed(2)})
32186
32321
  `;
32187
32322
  }
32188
32323
  if (u) {
32189
- let t = this.newQ.mergeToFront(Or, (t) => t.cardID);
32190
- D += `Additive merge: ${t} new cards added to front of newQ
32324
+ let t = this.newQ.mergeToFront(Mr, (t) => t.cardID, kr);
32325
+ Ar += `Additive merge: ${t} new cards added to front of newQ
32191
32326
  `;
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;
32327
+ } else if (c) this.newQ.replaceAll(Mr, (t) => t.cardID);
32328
+ else for (let t of Mr) this.newQ.add(t, t.cardID);
32329
+ return this.log(Ar), jr;
32195
32330
  }
32196
32331
  _getItemsToHydrate() {
32197
32332
  let t = [], c = 2;