@vue-skuilder/standalone-ui 0.2.2 → 0.2.4

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.
@@ -8662,7 +8662,7 @@ var stack$1, isWarning, ErrorCodes$1, ErrorTypeStrings$1, queue$1, flushIndex, p
8662
8662
  readonly: () => readonly,
8663
8663
  ref: () => ref,
8664
8664
  registerRuntimeCompiler: () => registerRuntimeCompiler,
8665
- render: () => render,
8665
+ render: () => render$1,
8666
8666
  renderList: () => renderList,
8667
8667
  renderSlot: () => renderSlot,
8668
8668
  resolveComponent: () => resolveComponent,
@@ -9165,7 +9165,7 @@ function normalizeContainer(t) {
9165
9165
  }
9166
9166
  return process.env.NODE_ENV !== "production" && window.ShadowRoot && t instanceof window.ShadowRoot && t.mode === "closed" && warn$2("mounting on a ShadowRoot with `{mode: \"closed\"}` may lead to unpredictable bugs"), t;
9167
9167
  }
9168
- var policy, tt$3, unsafeToTrustedHTML, svgNS, mathmlNS, doc, templateContainer, nodeOps, TRANSITION$1, ANIMATION, vtcKey, DOMTransitionPropsValidators, TransitionPropsValidators, decorate$1, Transition, callHook, hasExplicitCallback, endId, vShowOriginalDisplay, vShowHidden, vShow, CSS_VAR_TEXT, displayRE, semicolonRE, importantRE, prefixes, prefixCache, xlinkNS, veiKey, optionsModifierRE, cachedNow, p, getNow, isNativeOn, patchProp, REMOVAL, defineSSRCustomElement, BaseClass, VueElement, positionMap, newPositionMap, moveCbKey, enterCbKey, decorate, TransitionGroup, getModelAssigner, assignKey, vModelText, vModelCheckbox, vModelRadio, vModelSelect, vModelDynamic, systemModifiers, modifierGuards, withModifiers, keyNames, withKeys, rendererOptions, renderer, enabledHydration, render, hydrate, createApp, createSSRApp, ssrDirectiveInitialized, initDirectivesForSSR, init_runtime_dom_esm_bundler = __esmMin((() => {
9168
+ var policy, tt$3, unsafeToTrustedHTML, svgNS, mathmlNS, doc, templateContainer, nodeOps, TRANSITION$1, ANIMATION, vtcKey, DOMTransitionPropsValidators, TransitionPropsValidators, decorate$1, Transition, callHook, hasExplicitCallback, endId, vShowOriginalDisplay, vShowHidden, vShow, CSS_VAR_TEXT, displayRE, semicolonRE, importantRE, prefixes, prefixCache, xlinkNS, veiKey, optionsModifierRE, cachedNow, p, getNow, isNativeOn, patchProp, REMOVAL, defineSSRCustomElement, BaseClass, VueElement, positionMap, newPositionMap, moveCbKey, enterCbKey, decorate, TransitionGroup, getModelAssigner, assignKey, vModelText, vModelCheckbox, vModelRadio, vModelSelect, vModelDynamic, systemModifiers, modifierGuards, withModifiers, keyNames, withKeys, rendererOptions, renderer, enabledHydration, render$1, hydrate, createApp, createSSRApp, ssrDirectiveInitialized, initDirectivesForSSR, init_runtime_dom_esm_bundler = __esmMin((() => {
9169
9169
  if (init_runtime_core_esm_bundler(), init_runtime_core_esm_bundler(), init_shared_esm_bundler(), policy = void 0, tt$3 = typeof window < "u" && window.trustedTypes, tt$3) try {
9170
9170
  policy = /* @__PURE__ */ tt$3.createPolicy("vue", { createHTML: (t) => t });
9171
9171
  } catch (t) {
@@ -9330,7 +9330,7 @@ var policy, tt$3, unsafeToTrustedHTML, svgNS, mathmlNS, doc, templateContainer,
9330
9330
  }
9331
9331
  }
9332
9332
  _update() {
9333
- render(this._createVNode(), this._root);
9333
+ render$1(this._createVNode(), this._root);
9334
9334
  }
9335
9335
  _createVNode() {
9336
9336
  let t = {};
@@ -9563,9 +9563,9 @@ var policy, tt$3, unsafeToTrustedHTML, svgNS, mathmlNS, doc, templateContainer,
9563
9563
  let d = hyphenate(u.key);
9564
9564
  if (c.some((t) => t === d || keyNames[t] === d)) return t(u);
9565
9565
  });
9566
- }, rendererOptions = /* @__PURE__ */ extend$2({ patchProp }, nodeOps), enabledHydration = !1, render = (...t) => {
9566
+ }, rendererOptions = /* @__PURE__ */ extend$2({ patchProp }, nodeOps), enabledHydration = !1, render$1 = /* @__PURE__ */ __name$2((...t) => {
9567
9567
  ensureRenderer().render(...t);
9568
- }, hydrate = (...t) => {
9568
+ }, "render"), hydrate = (...t) => {
9569
9569
  ensureHydrationRenderer().hydrate(...t);
9570
9570
  }, createApp = (...t) => {
9571
9571
  let c = ensureRenderer().createApp(...t);
@@ -26489,6 +26489,85 @@ function mountMixerDebugger() {
26489
26489
  let t = window;
26490
26490
  t.skuilder = t.skuilder || {}, t.skuilder.mixer = mixerDebugAPI;
26491
26491
  }
26492
+ function registerActiveController(t) {
26493
+ activeController = t;
26494
+ }
26495
+ function getActiveController() {
26496
+ return activeController;
26497
+ }
26498
+ function toggleSessionOverlay() {
26499
+ if (typeof document > "u") {
26500
+ logger.info("[Session Overlay] No DOM available (non-browser host); overlay unavailable.");
26501
+ return;
26502
+ }
26503
+ overlayEl ? (teardown(), logger.info("[Session Overlay] Hidden.")) : (mount(), logger.info("[Session Overlay] Shown. Toggle off with window.skuilder.session.dbgOverlay()."));
26504
+ }
26505
+ function mount() {
26506
+ overlayEl = document.createElement("div"), overlayEl.id = OVERLAY_ID, Object.assign(overlayEl.style, {
26507
+ position: "fixed",
26508
+ top: "8px",
26509
+ left: "8px",
26510
+ zIndex: "2147483647",
26511
+ maxWidth: "320px",
26512
+ maxHeight: "90vh",
26513
+ overflowY: "auto",
26514
+ padding: "8px 10px",
26515
+ background: "rgba(17, 24, 39, 0.92)",
26516
+ color: "#e5e7eb",
26517
+ font: "11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace",
26518
+ borderRadius: "6px",
26519
+ boxShadow: "0 4px 16px rgba(0,0,0,0.4)",
26520
+ pointerEvents: "auto",
26521
+ userSelect: "none"
26522
+ }), document.body.appendChild(overlayEl), render(), pollHandle = setInterval(render, POLL_MS);
26523
+ }
26524
+ function teardown() {
26525
+ pollHandle !== null && (clearInterval(pollHandle), pollHandle = null), overlayEl?.parentNode && overlayEl.parentNode.removeChild(overlayEl), overlayEl = null;
26526
+ }
26527
+ function render() {
26528
+ if (!overlayEl) return;
26529
+ spinnerFrame++;
26530
+ let t = getActiveController();
26531
+ if (!t) {
26532
+ overlayEl.innerHTML = headerHtml() + "<div style=\"opacity:.65\">No active session.</div>";
26533
+ return;
26534
+ }
26535
+ let c = t.getDebugSnapshot();
26536
+ overlayEl.innerHTML = headerHtml() + replanHtml(c) + metaHtml(c) + hintsHtml(c.sessionHints) + queueHtml("reviewQ", "reviewQ", c.reviewQ) + queueHtml("newQ", "newQ", c.newQ) + queueHtml("failedQ", "failedQ", c.failedQ), overlayEl.querySelectorAll("[data-q]").forEach((t) => {
26537
+ t.onclick = () => {
26538
+ let c = t.dataset.q;
26539
+ c && (expanded[c] = !expanded[c], render());
26540
+ };
26541
+ });
26542
+ }
26543
+ function headerHtml() {
26544
+ return "<div style=\"font-weight:600;color:#93c5fd;margin-bottom:4px\">⚙ SessionController</div>";
26545
+ }
26546
+ function replanHtml(t) {
26547
+ return t.replanActive ? `<div style="margin-bottom:6px;color:#fde047">${SPINNER_FRAMES[spinnerFrame % SPINNER_FRAMES.length]} replanning <span style="opacity:.85">[${esc(t.replanLabel ?? "(auto)")}]</span></div>` : "<div style=\"margin-bottom:6px;opacity:.45\">○ idle</div>";
26548
+ }
26549
+ function metaHtml(t) {
26550
+ return `<div style="margin-bottom:6px">${[
26551
+ `time ${formatTime(t.secondsRemaining)}${t.hasCardGuarantee ? ` \xB7 <span style="color:#fbbf24">guarantee ${t.minCardsGuarantee}</span>` : ""}`,
26552
+ `well-indicated left: ${t.wellIndicatedRemaining}`,
26553
+ `current: ${t.currentCard ? esc(t.currentCard) : "<span style=\"opacity:.6\">—</span>"}`
26554
+ ].map((t) => `<div>${t}</div>`).join("")}</div>`;
26555
+ }
26556
+ function hintsHtml(t) {
26557
+ let c = [];
26558
+ return t && (t.boostTags && Object.keys(t.boostTags).length && c.push("boost: " + Object.entries(t.boostTags).map(([t, c]) => `${esc(t)}<span style="opacity:.6">\xD7${c}</span>`).join(", ")), t.boostCards && Object.keys(t.boostCards).length && c.push("boostCards: " + Object.entries(t.boostCards).map(([t, c]) => `${esc(t)}<span style="opacity:.6">\xD7${c}</span>`).join(", ")), t.requireCards?.length && c.push(`require: ${t.requireCards.map(esc).join(", ")}`), t.requireTags?.length && c.push(`requireTags: ${t.requireTags.map(esc).join(", ")}`), t.excludeTags?.length && c.push(`exclude: ${t.excludeTags.map(esc).join(", ")}`), t.excludeCards?.length && c.push(`excludeCards: ${t.excludeCards.map(esc).join(", ")}`)), `<div style="margin-bottom:6px"><div style="color:#86efac">sessionHints</div>${c.length ? c.map((t) => `<div style="margin-left:6px">${t}</div>`).join("") : "<div style=\"margin-left:6px;opacity:.6\">none</div>"}</div>`;
26559
+ }
26560
+ function queueHtml(t, c, u) {
26561
+ let d = u.length > INLINE_THRESHOLD, m = !d || expanded[t], g = d ? expanded[t] ? "▾ " : "▸ " : "", b = u.dequeueCount ? ` <span style="opacity:.5">drawn ${u.dequeueCount}</span>` : "", S = d ? "cursor:pointer;color:#f9a8d4" : "color:#f9a8d4", C = `<div${d ? ` data-q="${t}"` : ""} style="${S}">${g}${c}: ${u.length}${b}</div>`, w = "";
26562
+ return w = m && u.cards.length ? "<ol style=\"margin:2px 0 6px 0;padding-left:20px\">" + u.cards.map((t) => `<li style="white-space:nowrap">${esc(t)}</li>`).join("") + "</ol>" : u.cards.length ? `<div style="margin:1px 0 6px 6px;opacity:.55">(${u.length} cards \u2014 click to expand)</div>` : "<div style=\"margin:1px 0 6px 6px;opacity:.5\">empty</div>", C + w;
26563
+ }
26564
+ function formatTime(t) {
26565
+ let c = Math.max(0, Math.round(t));
26566
+ return `${Math.floor(c / 60)}:${(c % 60).toString().padStart(2, "0")}`;
26567
+ }
26568
+ function esc(t) {
26569
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
26570
+ }
26492
26571
  function startSessionTracking(t, c, u) {
26493
26572
  clearRunHistory();
26494
26573
  let d = `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
@@ -26599,7 +26678,7 @@ function mountSessionDebugger() {
26599
26678
  let t = window;
26600
26679
  t.skuilder = t.skuilder || {}, t.skuilder.session = sessionDebugAPI;
26601
26680
  }
26602
- 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, 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, activeSession, sessionHistory, MAX_HISTORY, sessionDebugAPI, SessionController, init_dist = __esmMin((() => {
26681
+ 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, 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, expanded, activeSession, sessionHistory, MAX_HISTORY, sessionDebugAPI, SessionController, init_dist = __esmMin((() => {
26603
26682
  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) => {
26604
26683
  var u = t[c];
26605
26684
  if (u) return u();
@@ -27958,7 +28037,10 @@ var import___vite_browser_external, import___vite_browser_external$1, import___v
27958
28037
  init_signal(), init_types_legacy(), init_logger();
27959
28038
  } }), init_orchestration = __esm({ "src/core/orchestration/index.ts"() {
27960
28039
  init_logger(), init_gradient(), init_learning(), init_signal(), init_recording(), MIN_SPREAD = .1, MAX_SPREAD = .5, MIN_WEIGHT = .1, MAX_WEIGHT = 3;
27961
- } }), Pipeline_exports = {}, __export(Pipeline_exports, { Pipeline: () => Pipeline }), init_Pipeline = __esm({ "src/core/navigators/Pipeline.ts"() {
28040
+ } }), Pipeline_exports = {}, __export(Pipeline_exports, {
28041
+ Pipeline: () => Pipeline,
28042
+ mergeHints: () => mergeHints2
28043
+ }), init_Pipeline = __esm({ "src/core/navigators/Pipeline.ts"() {
27962
28044
  init_navigators(), init_logger(), init_orchestration(), init_PipelineDebugger(), VERBOSE_RESULTS = !0, Pipeline = class extends ContentNavigator {
27963
28045
  constructor(t, c, u, d) {
27964
28046
  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) => {
@@ -30974,7 +31056,7 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
30974
31056
  return `${typeof this.q[0]}:
30975
31057
  ` + this.q.map((t) => ` ${t.courseID}+${t.cardID}: ${t.status}`).join("\n");
30976
31058
  }
30977
- }, init_couch(), init_recording(), init_Loggable(), init_types_legacy(), init_logger(), CouchDBToStaticPacker = class {
31059
+ }, init_couch(), init_core(), init_recording(), init_Loggable(), init_types_legacy(), init_logger(), CouchDBToStaticPacker = class {
30978
31060
  constructor(t = {}) {
30979
31061
  _defineProperty$2(this, "config", void 0), _defineProperty$2(this, "sourceDB", null), this.config = {
30980
31062
  chunkSize: 1e3,
@@ -31574,7 +31656,7 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31574
31656
  isLocalPath(t) {
31575
31657
  return !t.startsWith("http://") && !t.startsWith("https://");
31576
31658
  }
31577
- }, init_dataDirectory(), init_navigators(), QuotaRoundRobinMixer = class {
31659
+ }, init_dataDirectory(), init_navigators(), init_Pipeline(), QuotaRoundRobinMixer = class {
31578
31660
  mix(t, c) {
31579
31661
  if (t.length === 0) return [];
31580
31662
  let u = Math.ceil(c / t.length), d = t.map((t) => [...t.weighted].sort((t, c) => c.score - t.score).slice(0, u));
@@ -31687,7 +31769,22 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31687
31769
  help() {
31688
31770
  logger.info("\n🎨 Mixer Debug API\n\nCommands:\n .showLastMix() Show summary of most recent mixer run\n .showRun(id|index) Show summary of a specific run (by index or ID suffix)\n .explainSourceBalance() Analyze source balance and selection patterns\n .compareScores() Compare score distributions across sources\n .showCard(cardId) Show mixer decisions for a specific card\n .listRuns() List all captured runs in table format\n .export() Export run history as JSON for bug reports\n .clear() Clear run history\n .runs Access raw run history array\n .help() Show this help message\n\nExample:\n window.skuilder.mixer.showLastMix()\n window.skuilder.mixer.explainSourceBalance()\n window.skuilder.mixer.compareScores()\n");
31689
31771
  }
31690
- }, mountMixerDebugger(), init_logger(), init_PipelineDebugger(), activeSession = null, sessionHistory = [], MAX_HISTORY = 5, sessionDebugAPI = {
31772
+ }, mountMixerDebugger(), init_logger(), init_PipelineDebugger(), init_logger(), activeController = null, OVERLAY_ID = "skuilder-session-overlay", POLL_MS = 300, INLINE_THRESHOLD = 5, SPINNER_FRAMES = [
31773
+ "⠋",
31774
+ "⠙",
31775
+ "⠹",
31776
+ "⠸",
31777
+ "⠼",
31778
+ "⠴",
31779
+ "⠦",
31780
+ "⠧",
31781
+ "⠇",
31782
+ "⠏"
31783
+ ], spinnerFrame = 0, overlayEl = null, pollHandle = null, expanded = {
31784
+ reviewQ: !1,
31785
+ newQ: !1,
31786
+ failedQ: !1
31787
+ }, activeSession = null, sessionHistory = [], MAX_HISTORY = 5, sessionDebugAPI = {
31691
31788
  get sessions() {
31692
31789
  return [...sessionHistory];
31693
31790
  },
@@ -31697,6 +31794,9 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31697
31794
  showQueue() {
31698
31795
  showCurrentQueue();
31699
31796
  },
31797
+ dbgOverlay() {
31798
+ toggleSessionOverlay();
31799
+ },
31700
31800
  showHistory(t = 0) {
31701
31801
  showPresentationHistory(t);
31702
31802
  },
@@ -31727,7 +31827,7 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31727
31827
  sessionHistory.length = 0, logger.info("[Session Debug] Session history cleared.");
31728
31828
  },
31729
31829
  help() {
31730
- logger.info("\n🎯 Session Debug API\n\nCommands:\n .showQueue() Show current queue state (active session only)\n .showHistory(index?) Show presentation history (0=current/last, 1=previous, etc)\n .showInterleaving(index?) Analyze course interleaving pattern\n .listSessions() List all tracked sessions\n .export() Export session data as JSON for bug reports\n .clear() Clear session history\n .sessions Access raw session history array\n .active Access active session (if any)\n .help() Show this help message\n\nExample:\n window.skuilder.session.showHistory()\n window.skuilder.session.showInterleaving()\n window.skuilder.session.showQueue()\n");
31830
+ logger.info("\n🎯 Session Debug API\n\nCommands:\n .dbgOverlay() Toggle the pinned live overlay (queues, hints, timer)\n .showQueue() Show current queue state (active session only)\n .showHistory(index?) Show presentation history (0=current/last, 1=previous, etc)\n .showInterleaving(index?) Analyze course interleaving pattern\n .listSessions() List all tracked sessions\n .export() Export session data as JSON for bug reports\n .clear() Clear session history\n .sessions Access raw session history array\n .active Access active session (if any)\n .help() Show this help message\n\nExample:\n window.skuilder.session.showHistory()\n window.skuilder.session.showInterleaving()\n window.skuilder.session.showQueue()\n");
31731
31831
  }
31732
31832
  }, mountSessionDebugger(), init_logger(), SessionController = (_SessionController2 = class _SessionController extends Loggable {
31733
31833
  set sessionRecord(t) {
@@ -31747,11 +31847,11 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31747
31847
  return this.newQ.toString + "\n" + this.reviewQ.toString + "\n" + this.failedQ.toString;
31748
31848
  }
31749
31849
  constructor(t, c, u, d, m, g) {
31750
- super(), _defineProperty$2(this, "_className", "SessionController"), _defineProperty$2(this, "services", void 0), _defineProperty$2(this, "srsService", void 0), _defineProperty$2(this, "eloService", void 0), _defineProperty$2(this, "hydrationService", void 0), _defineProperty$2(this, "mixer", void 0), _defineProperty$2(this, "dataLayer", void 0), _defineProperty$2(this, "courseNameCache", /* @__PURE__ */ new Map()), _defineProperty$2(this, "_defaultBatchLimit", 20), _defineProperty$2(this, "_initialReviewCap", 200), _defineProperty$2(this, "sources", void 0), _defineProperty$2(this, "_sessionRecord", []), _defineProperty$2(this, "_currentCard", null), _defineProperty$2(this, "reviewQ", new ItemQueue()), _defineProperty$2(this, "newQ", new ItemQueue()), _defineProperty$2(this, "failedQ", new ItemQueue()), _defineProperty$2(this, "_replanPromise", null), _defineProperty$2(this, "_wellIndicatedRemaining", 0), _defineProperty$2(this, "_suppressQualityReplan", !1), _defineProperty$2(this, "_minCardsGuarantee", 0), _defineProperty$2(this, "startTime", void 0), _defineProperty$2(this, "endTime", void 0), _defineProperty$2(this, "_secondsRemaining", void 0), _defineProperty$2(this, "_intervalHandle", void 0), this.dataLayer = u, this.mixer = m || new QuotaRoundRobinMixer(), this.srsService = new SrsService(u.getUserDB()), this.eloService = new EloService(u, u.getUserDB()), this.hydrationService = new CardHydrationService(d, (t) => u.getCourseDB(t), () => this._getItemsToHydrate()), this.services = { response: new ResponseProcessor(this.srsService, this.eloService) }, this.sources = t, this.startTime = /* @__PURE__ */ new Date(), this._secondsRemaining = c, this.endTime = new Date(this.startTime.valueOf() + 1e3 * this._secondsRemaining), g?.defaultBatchLimit !== void 0 && (this._defaultBatchLimit = g.defaultBatchLimit), g?.initialReviewCap !== void 0 && (this._initialReviewCap = g.initialReviewCap), this.log(`Session constructed:
31850
+ super(), _defineProperty$2(this, "_className", "SessionController"), _defineProperty$2(this, "services", void 0), _defineProperty$2(this, "srsService", void 0), _defineProperty$2(this, "eloService", void 0), _defineProperty$2(this, "hydrationService", void 0), _defineProperty$2(this, "mixer", void 0), _defineProperty$2(this, "dataLayer", void 0), _defineProperty$2(this, "courseNameCache", /* @__PURE__ */ new Map()), _defineProperty$2(this, "_defaultBatchLimit", 20), _defineProperty$2(this, "_initialReviewCap", 200), _defineProperty$2(this, "sources", void 0), _defineProperty$2(this, "_sessionRecord", []), _defineProperty$2(this, "_currentCard", null), _defineProperty$2(this, "reviewQ", new ItemQueue()), _defineProperty$2(this, "newQ", new ItemQueue()), _defineProperty$2(this, "failedQ", new ItemQueue()), _defineProperty$2(this, "_replanPromise", null), _defineProperty$2(this, "_activeReplanLabel", null), _defineProperty$2(this, "_wellIndicatedRemaining", 0), _defineProperty$2(this, "_suppressQualityReplan", !1), _defineProperty$2(this, "_minCardsGuarantee", 0), _defineProperty$2(this, "_sessionHints", null), _defineProperty$2(this, "_outcomeObservers", []), _defineProperty$2(this, "_sessionControls", null), _defineProperty$2(this, "startTime", void 0), _defineProperty$2(this, "endTime", void 0), _defineProperty$2(this, "_secondsRemaining", void 0), _defineProperty$2(this, "_intervalHandle", void 0), this.dataLayer = u, this.mixer = m || new QuotaRoundRobinMixer(), this.srsService = new SrsService(u.getUserDB()), this.eloService = new EloService(u, u.getUserDB()), this.hydrationService = new CardHydrationService(d, (t) => u.getCourseDB(t), () => this._getItemsToHydrate()), this.services = { response: new ResponseProcessor(this.srsService, this.eloService) }, this.sources = t, this.startTime = /* @__PURE__ */ new Date(), this._secondsRemaining = c, this.endTime = new Date(this.startTime.valueOf() + 1e3 * this._secondsRemaining), g?.defaultBatchLimit !== void 0 && (this._defaultBatchLimit = g.defaultBatchLimit), g?.initialReviewCap !== void 0 && (this._initialReviewCap = g.initialReviewCap), g?.outcomeObservers?.length && (this._outcomeObservers = [...g.outcomeObservers]), this.log(`Session constructed:
31751
31851
  startTime: ${this.startTime}
31752
31852
  endTime: ${this.endTime}
31753
31853
  defaultBatchLimit: ${this._defaultBatchLimit}
31754
- initialReviewCap: ${this._initialReviewCap}`);
31854
+ initialReviewCap: ${this._initialReviewCap}`), registerActiveController(this);
31755
31855
  }
31756
31856
  tick() {
31757
31857
  this._secondsRemaining = Math.floor((this.endTime.valueOf() - Date.now()) / 1e3), this._secondsRemaining <= 0 && clearInterval(this._intervalHandle);
@@ -31785,44 +31885,100 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31785
31885
  if (!u) return this.log("Replan already in progress, coalescing unhinted auto-replan"), this._replanPromise;
31786
31886
  let t = c.label ? ` [${c.label}]` : "";
31787
31887
  this.log(`Replan in progress; queueing hint-bearing replan${t} behind in-flight run`);
31788
- let d = this._replanPromise.catch(() => void 0).then(() => this._runReplan(c));
31789
- return this._replanPromise = d.finally(() => {
31790
- this._replanPromise === d && (this._replanPromise = null);
31791
- }), d;
31888
+ let d = this._replanPromise.catch(() => void 0).then(() => this._runReplan(c)), m = d.finally(() => {
31889
+ this._replanPromise === m && (this._replanPromise = null, this._activeReplanLabel = null);
31890
+ });
31891
+ return this._replanPromise = m, d;
31792
31892
  }
31793
- let d = this._runReplan(c);
31794
- this._replanPromise = d.finally(() => {
31795
- this._replanPromise === d && (this._replanPromise = null);
31796
- }), await d;
31893
+ let d = this._runReplan(c), m = d.finally(() => {
31894
+ this._replanPromise === m && (this._replanPromise = null, this._activeReplanLabel = null);
31895
+ });
31896
+ this._replanPromise = m, await d;
31797
31897
  }
31798
31898
  _replanHasIntent(t) {
31799
- return !!(t.label || t.limit !== void 0 || t.minFollowUpCards !== void 0 || t.mode && t.mode !== "replace" || t.hints && Object.keys(t.hints).length > 0);
31899
+ return !!(t.limit !== void 0 || t.minFollowUpCards !== void 0 || t.mode && t.mode !== "replace" || t.hints && Object.keys(t.hints).length > 0 || t.sessionHints !== void 0);
31800
31900
  }
31801
31901
  async _runReplan(t) {
31802
- t.hints || (t.hints = {});
31902
+ this._activeReplanLabel = t.label ?? "(auto)", t.hints || (t.hints = {});
31803
31903
  let c = t.hints, u = new Set(c.excludeCards ?? []);
31804
31904
  this._currentCard?.item.cardID && u.add(this._currentCard.item.cardID);
31805
31905
  for (let t of this._sessionRecord) u.add(t.card.card_id);
31806
- if (this.newQ.length > 0 && u.add(this.newQ.peek(0).cardID), c.excludeCards = [...u], t.hints) {
31807
- let c = t.label ? {
31808
- ...t.hints,
31809
- _label: t.label
31810
- } : t.hints;
31811
- for (let t of this.sources) t.setEphemeralHints?.(c);
31812
- }
31906
+ this.newQ.length > 0 && u.add(this.newQ.peek(0).cardID), c.excludeCards = [...u], t.sessionHints !== void 0 && (this._sessionHints = t.sessionHints, this.log(`[Replan] Session hints ${t.sessionHints ? "set" : "cleared"}: ${JSON.stringify(t.sessionHints)}`)), this._applyHintsToSources(t.hints, t.label);
31813
31907
  let d = t.label ? ` [${t.label}]` : "";
31814
31908
  this.log(`Mid-session replan requested${d} (limit: ${t.limit ?? "default"}, mode: ${t.mode ?? "replace"}${t.hints ? ", with hints" : ""})`), t.minFollowUpCards !== void 0 && t.minFollowUpCards > 0 && (this._minCardsGuarantee = Math.max(this._minCardsGuarantee, t.minFollowUpCards), this.log(`[Replan] Card guarantee set to ${this._minCardsGuarantee}`)), await this._executeReplan(t);
31815
31909
  }
31910
+ setSessionHints(t) {
31911
+ this._sessionHints = t, this.log(`Session hints ${t ? "set" : "cleared"}: ${JSON.stringify(t)}`);
31912
+ }
31913
+ getSessionHints() {
31914
+ return this._sessionHints;
31915
+ }
31916
+ getDebugSnapshot() {
31917
+ let describe = (t) => {
31918
+ let c = [];
31919
+ for (let u = 0; u < t.length; u++) c.push(t.peek(u).cardID);
31920
+ return {
31921
+ length: t.length,
31922
+ dequeueCount: t.dequeueCount,
31923
+ cards: c
31924
+ };
31925
+ };
31926
+ return {
31927
+ secondsRemaining: this.secondsRemaining,
31928
+ hasCardGuarantee: this.hasCardGuarantee,
31929
+ minCardsGuarantee: this._minCardsGuarantee,
31930
+ wellIndicatedRemaining: this._wellIndicatedRemaining,
31931
+ currentCard: this._currentCard?.item.cardID ?? null,
31932
+ sessionHints: this._sessionHints,
31933
+ replanActive: this._replanPromise !== null,
31934
+ replanLabel: this._activeReplanLabel,
31935
+ reviewQ: describe(this.reviewQ),
31936
+ newQ: describe(this.newQ),
31937
+ failedQ: describe(this.failedQ)
31938
+ };
31939
+ }
31940
+ mergeSessionHints(t) {
31941
+ this._sessionHints = mergeHints2([this._sessionHints, t]) ?? null, this.log(`Session hints merged: ${JSON.stringify(this._sessionHints)}`);
31942
+ }
31943
+ _applyHintsToSources(t, c) {
31944
+ let u = t && c ? {
31945
+ ...t,
31946
+ _label: c
31947
+ } : t, d = mergeHints2([this._sessionHints, u]);
31948
+ if (d) for (let t of this.sources) t.setEphemeralHints?.(d);
31949
+ }
31950
+ _getSessionControls() {
31951
+ return this._sessionControls || (this._sessionControls = {
31952
+ getSessionHints: () => this.getSessionHints(),
31953
+ setSessionHints: (t) => this.setSessionHints(t),
31954
+ mergeSessionHints: (t) => this.mergeSessionHints(t),
31955
+ requestReplan: (t) => this.requestReplan(t)
31956
+ }), this._sessionControls;
31957
+ }
31958
+ async _notifyOutcomeObservers(t, c, u) {
31959
+ if (this._outcomeObservers.length === 0 || !isQuestionRecord(t)) return;
31960
+ let d = {
31961
+ record: t,
31962
+ card: c.card,
31963
+ result: u
31964
+ }, m = this._getSessionControls();
31965
+ for (let t of this._outcomeObservers) try {
31966
+ await t(d, m);
31967
+ } catch (t) {
31968
+ this.error("[OutcomeObserver] observer threw; ignoring", t);
31969
+ }
31970
+ }
31816
31971
  async _replanUncoalesced(t) {
31817
- let c = this._runReplan(t);
31818
- this._replanPromise = c.finally(() => {
31819
- this._replanPromise === c && (this._replanPromise = null);
31820
- }), await c;
31972
+ let c = this._runReplan(t), u = c.finally(() => {
31973
+ this._replanPromise === u && (this._replanPromise = null, this._activeReplanLabel = null);
31974
+ });
31975
+ this._replanPromise = u, await c;
31821
31976
  }
31822
31977
  normalizeReplanOptions(t) {
31823
31978
  if (!t) return {};
31824
31979
  let c = [
31825
31980
  "hints",
31981
+ "sessionHints",
31826
31982
  "limit",
31827
31983
  "mode",
31828
31984
  "label",
@@ -31898,7 +32054,9 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31898
32054
  };
31899
32055
  }
31900
32056
  async getWeightedContent(t) {
31901
- let c = t?.replan ?? !1, u = t?.additive ?? !1, d = t?.limit ?? this._defaultBatchLimit, m = c ? d : d + this._initialReviewCap, g = [];
32057
+ let c = t?.replan ?? !1, u = t?.additive ?? !1, d = t?.limit ?? this._defaultBatchLimit, m = c ? d : d + this._initialReviewCap;
32058
+ c || this._applyHintsToSources();
32059
+ let g = [];
31902
32060
  for (let t = 0; t < this.sources.length; t++) {
31903
32061
  let c = this.sources[t];
31904
32062
  try {
@@ -31978,9 +32136,9 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
31978
32136
  if (this.dismissCurrentCard(t), this._minCardsGuarantee > 0 && (this._minCardsGuarantee--, this.log(`[CardGuarantee] ${this._minCardsGuarantee} guaranteed cards remaining`)), this._replanPromise && this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0 && (this.log("nextCard: queues empty, awaiting in-flight replan before drawing"), await this._replanPromise), this.newQ.length <= _SessionController.DEPLETION_PREFETCH_THRESHOLD && this._secondsRemaining > 0 && !this._replanPromise) {
31979
32137
  this._suppressQualityReplan = !1;
31980
32138
  let t = this.reviewQ.length + this.failedQ.length;
31981
- this.log(`[AutoReplan:depletion] newQ has ${this.newQ.length} card(s) (${t} in other queues) with ${this._secondsRemaining}s remaining. Triggering background replan.`), this.requestReplan();
32139
+ this.log(`[AutoReplan:depletion] newQ has ${this.newQ.length} card(s) (${t} in other queues) with ${this._secondsRemaining}s remaining. Triggering background replan.`), this.requestReplan({ label: "auto:depletion" });
31982
32140
  }
31983
- if (!this._suppressQualityReplan && this._wellIndicatedRemaining <= 3 && this.newQ.length > 0 && !this._replanPromise && (this.log(`[AutoReplan:quality] ${this._wellIndicatedRemaining} well-indicated cards remaining (newQ: ${this.newQ.length}). Triggering background replan.`), this.requestReplan()), this._secondsRemaining <= 0 && this.failedQ.length === 0 && this._minCardsGuarantee <= 0) return this._currentCard = null, endSessionTracking(), null;
32141
+ if (!this._suppressQualityReplan && this._wellIndicatedRemaining <= 3 && this.newQ.length > 0 && !this._replanPromise && (this.log(`[AutoReplan:quality] ${this._wellIndicatedRemaining} well-indicated cards remaining (newQ: ${this.newQ.length}). Triggering background replan.`), this.requestReplan({ label: "auto:quality" })), this._secondsRemaining <= 0 && this.failedQ.length === 0 && this._minCardsGuarantee <= 0) return this._currentCard = null, endSessionTracking(), null;
31984
32142
  let c = 3, u = 250, d = 0;
31985
32143
  for (; this._secondsRemaining > 0 && this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0;) if (this.log(`[WedgeBreaker] All queues empty with ${this._secondsRemaining}s remaining. Running pipeline (attempt ${d + 1}/3).`), await this._replanUncoalesced({ label: "wedge-breaker" }), this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0) {
31986
32144
  if (d++, d >= 3) {
@@ -32004,8 +32162,8 @@ ${c.id}:`), logger.info(JSON.stringify(c.doc, null, 2));
32004
32162
  return this.log("Exhausted 20 skip attempts finding a hydratable card"), this._currentCard = null, endSessionTracking(), null;
32005
32163
  }
32006
32164
  async submitResponse(t, c, u, d, m, g, b, S, C) {
32007
- let w = { ...d.item };
32008
- return await this.services.response.processResponse(t, c, w, u, d, m, g, b, S, C);
32165
+ let w = { ...d.item }, T = await this.services.response.processResponse(t, c, w, u, d, m, g, b, S, C);
32166
+ return await this._notifyOutcomeObservers(t, d, T), T;
32009
32167
  }
32010
32168
  dismissCurrentCard(t = "dismiss-success") {
32011
32169
  if (this._currentCard) if (t === "dismiss-success") this.hydrationService.removeCard(this._currentCard.item.cardID);
@@ -42954,11 +43112,7 @@ var Ee$1, De$1, Oe$1, ke$1, Ae$1, je$1, Me$1, Ne$1, Pe$1, Fe$1, Ie$1, Le$1, Z$2,
42954
43112
  }
42955
43113
  }))).filter((t) => t !== null)), this.timeRemaining = this.sessionTimeLimit * 60, t = await Promise.all(this.contentSources.filter((t) => t.type === "classroom").map(async (t) => await this.dataLayer.getClassroomDB(t.id, "student"))), t.forEach((t) => {});
42956
43114
  let c = {};
42957
- if (this.sessionConfig?.defaultBatchLimit !== void 0 && (c.defaultBatchLimit = this.sessionConfig.defaultBatchLimit), this.sessionConfig?.initialReviewCap !== void 0 && (c.initialReviewCap = this.sessionConfig.initialReviewCap), this.sessionController = markRaw(new SessionController(this.sessionContentSources, 60 * this.sessionTimeLimit, this.dataLayer, this.getViewComponent, void 0, c)), this.sessionController.sessionRecord = this.sessionRecord, this.sessionConfig?.initHints) {
42958
- for (let t of this.sessionContentSources) t.setEphemeralHints?.(this.sessionConfig.initHints);
42959
- console.log("[StudySession] Applied init hints to content sources");
42960
- }
42961
- await this.sessionController.prepareSession(), this.intervalHandler = setInterval(this.tick, 1e3), this.sessionPrepared = !0, console.log("[StudySession] Session preparation complete, emitting session-prepared event"), this.$emit("session-prepared"), console.log("[StudySession] Event emission completed");
43115
+ this.sessionConfig?.defaultBatchLimit !== void 0 && (c.defaultBatchLimit = this.sessionConfig.defaultBatchLimit), this.sessionConfig?.initialReviewCap !== void 0 && (c.initialReviewCap = this.sessionConfig.initialReviewCap), this.sessionConfig?.outcomeObservers?.length && (c.outcomeObservers = this.sessionConfig.outcomeObservers), this.sessionController = markRaw(new SessionController(this.sessionContentSources, 60 * this.sessionTimeLimit, this.dataLayer, this.getViewComponent, void 0, c)), this.sessionController.sessionRecord = this.sessionRecord, this.sessionConfig?.initHints && (this.sessionController.setSessionHints(this.sessionConfig.initHints), console.log("[StudySession] Applied init hints as session-durable hints")), await this.sessionController.prepareSession(), this.intervalHandler = setInterval(this.tick, 1e3), this.sessionPrepared = !0, console.log("[StudySession] Session preparation complete, emitting session-prepared event"), this.$emit("session-prepared"), console.log("[StudySession] Event emission completed");
42962
43116
  } catch (t) {
42963
43117
  console.error("[StudySession] Error during session preparation:", t), this.$emit("session-error", {
42964
43118
  message: "Failed to prepare study session",
@@ -43075,7 +43229,7 @@ var Ee$1, De$1, Oe$1, ke$1, Ae$1, je$1, Me$1, Ne$1, Pe$1, Fe$1, Ie$1, Le$1, Z$2,
43075
43229
  key: 4,
43076
43230
  ref: "shadowWrapper",
43077
43231
  class: "card-transition-container"
43078
- }, on = { key: 0 }, __name(_sfc_render$15, "_sfc_render"), sn = /* @__PURE__ */ F$3(Qt, [["render", _sfc_render$15], ["__scopeId", "data-v-bc445530"]]), cn = /* @__PURE__ */ defineComponent({
43232
+ }, on = { key: 0 }, __name(_sfc_render$15, "_sfc_render"), sn = /* @__PURE__ */ F$3(Qt, [["render", _sfc_render$15], ["__scopeId", "data-v-de7119e9"]]), cn = /* @__PURE__ */ defineComponent({
43079
43233
  name: "MultipleChoiceOption",
43080
43234
  components: { MarkdownRenderer: /* @__PURE__ */ defineAsyncComponent(() => Promise.resolve().then(() => (init_MarkdownRenderer_DoVbFpA6(), MarkdownRenderer_DoVbFpA6_exports)).then((t) => t.n)) },
43081
43235
  props: {