@vue-skuilder/db 0.2.11 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2896,7 +2896,7 @@ __export(srs_exports, {
2896
2896
  default: () => SRSNavigator
2897
2897
  });
2898
2898
  import moment3 from "moment";
2899
- var DEFAULT_HEALTHY_BACKLOG, MAX_BACKLOG_MULTIPLIER, SRSNavigator;
2899
+ var DEFAULT_HEALTHY_BACKLOG, BACKLOG_GROWTH_RATE, SRSNavigator;
2900
2900
  var init_srs = __esm({
2901
2901
  "src/core/navigators/generators/srs.ts"() {
2902
2902
  "use strict";
@@ -2904,7 +2904,7 @@ var init_srs = __esm({
2904
2904
  init_SrsDebugger();
2905
2905
  init_logger();
2906
2906
  DEFAULT_HEALTHY_BACKLOG = 20;
2907
- MAX_BACKLOG_MULTIPLIER = 2;
2907
+ BACKLOG_GROWTH_RATE = 2;
2908
2908
  SRSNavigator = class extends ContentNavigator {
2909
2909
  /** Human-readable name for CardGenerator interface */
2910
2910
  name;
@@ -3026,7 +3026,7 @@ var init_srs = __esm({
3026
3026
  dueNow: dueReviews.length,
3027
3027
  healthyBacklog: this.healthyBacklog,
3028
3028
  backlogMultiplier,
3029
- maxBacklogMultiplier: MAX_BACKLOG_MULTIPLIER,
3029
+ backlogGrowthRate: BACKLOG_GROWTH_RATE,
3030
3030
  topReviewScore: sorted.length > 0 ? sorted[0].score : null,
3031
3031
  nextDueIn,
3032
3032
  timestamp: Date.now()
@@ -3036,25 +3036,30 @@ var init_srs = __esm({
3036
3036
  /**
3037
3037
  * Compute the multiplicative backlog pressure based on number of due reviews.
3038
3038
  *
3039
- * ×1.0 at or below the healthy threshold (no boost), increasing linearly above
3040
- * it and maxing out at MAX_BACKLOG_MULTIPLIER at the healthy backlog.
3039
+ * ×1.0 at or below the healthy threshold (no boost); above it, grows as
3040
+ * BACKLOG_GROWTH_RATE raised to the excess expressed in multiples of the
3041
+ * healthy threshold. Uncapped — self-regulating instead: reviews winning
3042
+ * slots depletes dueCount, which drops the ratio and relaxes the multiplier
3043
+ * next run.
3041
3044
  *
3042
- * Examples (with default healthyBacklog=20, MAX_BACKLOG_MULTIPLIER=2.0):
3043
- * - 10 due reviews → ×1.00 (healthy)
3044
- * - 20 due reviews → ×1.00 (at threshold)
3045
- * - 40 due reviews → ×1.50 (2x threshold)
3046
- * - 60 due reviews → ×2.00 (3x threshold, maxed)
3045
+ * Examples (with default healthyBacklog=20, BACKLOG_GROWTH_RATE=1.5):
3046
+ * - 10 due reviews → ×1.00 (healthy)
3047
+ * - 20 due reviews → ×1.00 (at threshold, ratio 0)
3048
+ * - 40 due reviews → ×1.50 (ratio 1, 2x threshold)
3049
+ * - 60 due reviews → ×2.25 (ratio 2, 3x threshold — old hard cap was ×2.00 here)
3050
+ * - 100 due reviews → ×5.06 (ratio 4, 5x threshold)
3051
+ * - 160 due reviews → ×17.09 (ratio 7, 8x threshold)
3047
3052
  *
3048
3053
  * @param dueCount - Number of reviews currently due
3049
- * @returns Multiplier applied to review urgency (1.0 to MAX_BACKLOG_MULTIPLIER)
3054
+ * @returns Multiplier applied to review urgency (>= 1.0, unbounded)
3050
3055
  */
3051
3056
  computeBacklogMultiplier(dueCount) {
3052
3057
  if (dueCount <= this.healthyBacklog) {
3053
3058
  return 1;
3054
3059
  }
3055
3060
  const excess = dueCount - this.healthyBacklog;
3056
- const multiplier = 1 + excess / this.healthyBacklog * ((MAX_BACKLOG_MULTIPLIER - 1) / 2);
3057
- return Math.min(MAX_BACKLOG_MULTIPLIER, multiplier);
3061
+ const ratio = excess / this.healthyBacklog;
3062
+ return Math.pow(BACKLOG_GROWTH_RATE, ratio);
3058
3063
  }
3059
3064
  /**
3060
3065
  * Compute urgency score for a review card.
@@ -3070,17 +3075,17 @@ var init_srs = __esm({
3070
3075
  * - 180 days → ~0.30
3071
3076
  *
3072
3077
  * 3. Backlog pressure = global *multiplier* when review backlog exceeds the
3073
- * healthy threshold (×1.0 healthy → up to MAX_BACKLOG_MULTIPLIER at ).
3078
+ * healthy threshold (×1.0 healthy → exponential growth, uncapped, above it).
3074
3079
  *
3075
3080
  * Combined: (base 0.5 + urgency factors * 0.45) × backlog multiplier.
3076
3081
  * Per-card range before pressure: ~0.57–0.95. NOT clamped to 1.0 — under a
3077
3082
  * heavy backlog reviews scale onto the open scale to compete with (and exceed)
3078
- * new cards; what keeps them from running away is the bounded multiplier, not
3079
- * a hard ceiling.
3083
+ * new cards; there's no ceiling at all now, so a bad enough backlog always
3084
+ * wins eventually — self-regulating because winning slots depletes dueCount.
3080
3085
  *
3081
3086
  * @param review - The scheduled card to score
3082
3087
  * @param now - Current time
3083
- * @param backlogMultiplier - Pre-computed backlog multiplier (1.0 to MAX_BACKLOG_MULTIPLIER)
3088
+ * @param backlogMultiplier - Pre-computed backlog multiplier (>= 1.0, unbounded)
3084
3089
  */
3085
3090
  computeUrgencyScore(review, now, backlogMultiplier) {
3086
3091
  const scheduledAt = moment3.utc(review.scheduledAt);
@@ -7393,6 +7398,14 @@ var init_CouchDBSyncStrategy = __esm({
7393
7398
  } else {
7394
7399
  logger.info("No documents to migrate from funnel account");
7395
7400
  }
7401
+ try {
7402
+ await oldLocalDB.destroy();
7403
+ logger.info(`Destroyed consumed guest DB for ${oldUsername}`);
7404
+ } catch (destroyErr) {
7405
+ logger.warn(
7406
+ `Failed to destroy consumed guest DB for ${oldUsername} (non-fatal): ${destroyErr instanceof Error ? destroyErr.message : String(destroyErr)}`
7407
+ );
7408
+ }
7396
7409
  return { success: true };
7397
7410
  } catch (error) {
7398
7411
  logger.error("Migration failed:", error);
@@ -7824,6 +7837,11 @@ Currently logged-in as ${this._username}.`
7824
7837
  return { ok: true };
7825
7838
  }
7826
7839
  const ret = await this.syncStrategy.logout();
7840
+ try {
7841
+ localStorage.removeItem("sk-guest-uuid");
7842
+ } catch (e) {
7843
+ logger.warn("localStorage not available (Node.js environment):", e);
7844
+ }
7827
7845
  this._username = await this.syncStrategy.getCurrentUsername();
7828
7846
  await this.init();
7829
7847
  return ret;
@@ -13629,12 +13647,12 @@ function hintsHtml(h) {
13629
13647
  function backlogHtml(backlog) {
13630
13648
  if (!backlog.length) return "";
13631
13649
  const rows = backlog.map((b) => {
13632
- const maxed = b.backlogMultiplier >= b.maxBacklogMultiplier - 1e-9;
13633
- const multColor = b.backlogMultiplier <= 1 ? "#86efac" : maxed ? "#fca5a5" : "#fcd34d";
13634
- const headroom = maxed ? "maxed \u2014 boosts decide order until they relax" : b.backlogMultiplier > 1 ? "climbing as backlog grows" : "healthy \u2014 no pressure";
13650
+ const hot = b.backlogMultiplier >= 3;
13651
+ const multColor = b.backlogMultiplier <= 1 ? "#86efac" : hot ? "#fca5a5" : "#fcd34d";
13652
+ const headroom = b.backlogMultiplier > 1 ? `climbing (\xD7${b.backlogGrowthRate.toFixed(2)} per ${b.healthyBacklog}-review excess, unbounded)` : "healthy \u2014 no pressure";
13635
13653
  const top = b.topReviewScore !== null ? b.topReviewScore.toFixed(2) : "\u2014";
13636
13654
  const next = b.nextDueIn ? ` <span style="opacity:.6">\xB7 next due ${esc(b.nextDueIn)}</span>` : "";
13637
- return `<div style="margin-left:6px"><span style="opacity:.7">${esc(b.courseId.slice(0, 8))}</span> due ${b.dueNow}/${b.scheduledTotal} <span style="opacity:.6">(healthy ${b.healthyBacklog})</span>${next}<div style="margin-left:6px">pressure <span style="color:${multColor}">\xD7${b.backlogMultiplier.toFixed(2)}/${b.maxBacklogMultiplier.toFixed(2)}</span> <span style="opacity:.6">${headroom} \xB7 top review ${top}</span></div></div>`;
13655
+ return `<div style="margin-left:6px"><span style="opacity:.7">${esc(b.courseId.slice(0, 8))}</span> due ${b.dueNow}/${b.scheduledTotal} <span style="opacity:.6">(healthy ${b.healthyBacklog})</span>${next}<div style="margin-left:6px">pressure <span style="color:${multColor}">\xD7${b.backlogMultiplier.toFixed(2)}</span> <span style="opacity:.6">${headroom} \xB7 top review ${top}</span></div></div>`;
13638
13656
  }).join("");
13639
13657
  return `<div style="margin-bottom:6px"><div style="color:#93c5fd">review backpressure</div>${rows}</div>`;
13640
13658
  }
@@ -13730,12 +13748,11 @@ function snapshotToText(s) {
13730
13748
  lines.push("");
13731
13749
  lines.push("review backpressure:");
13732
13750
  for (const b of s.reviewBacklog) {
13733
- const maxed = b.backlogMultiplier >= b.maxBacklogMultiplier - 1e-9;
13734
- const headroom = maxed ? "maxed (boosts decide order)" : b.backlogMultiplier > 1 ? "climbing" : "healthy";
13751
+ const headroom = b.backlogMultiplier > 1 ? "climbing" : "healthy";
13735
13752
  const top = b.topReviewScore !== null ? b.topReviewScore.toFixed(2) : "\u2014";
13736
13753
  const next = b.nextDueIn ? `, next due ${b.nextDueIn}` : "";
13737
13754
  lines.push(
13738
- ` ${b.courseId.slice(0, 8)}: due ${b.dueNow}/${b.scheduledTotal} (healthy ${b.healthyBacklog})${next}; pressure \xD7${b.backlogMultiplier.toFixed(2)}/${b.maxBacklogMultiplier.toFixed(2)} ${headroom}; top review ${top}`
13755
+ ` ${b.courseId.slice(0, 8)}: due ${b.dueNow}/${b.scheduledTotal} (healthy ${b.healthyBacklog})${next}; pressure \xD7${b.backlogMultiplier.toFixed(2)} ${headroom}; top review ${top}`
13739
13756
  );
13740
13757
  }
13741
13758
  }
@@ -13773,9 +13790,11 @@ function esc(value) {
13773
13790
  var activeSession = null;
13774
13791
  var sessionHistory = [];
13775
13792
  var MAX_HISTORY = 5;
13776
- function startSessionTracking(supplyQLength, failedQLength) {
13793
+ function clearStaleSessionDebugState() {
13777
13794
  clearRunHistory();
13778
13795
  clearSrsBacklogDebug();
13796
+ }
13797
+ function startSessionTracking(supplyQLength, failedQLength) {
13779
13798
  const sessionId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
13780
13799
  activeSession = {
13781
13800
  sessionId,
@@ -14257,6 +14276,7 @@ var SessionController = class _SessionController extends Loggable {
14257
14276
  "[SessionController] All content sources must implement getWeightedCards()."
14258
14277
  );
14259
14278
  }
14279
+ clearStaleSessionDebugState();
14260
14280
  const wellIndicated = await this.getWeightedContent();
14261
14281
  this._wellIndicatedRemaining = wellIndicated;
14262
14282
  if (wellIndicated >= 0 && wellIndicated < _SessionController.MIN_WELL_INDICATED) {
@@ -15160,6 +15180,7 @@ export {
15160
15180
  buildStrategyStateId,
15161
15181
  captureMixerRun,
15162
15182
  clearSrsBacklogDebug,
15183
+ clearStaleSessionDebugState,
15163
15184
  computeDeviation,
15164
15185
  computeEffectiveWeight,
15165
15186
  computeOutcomeSignal,