@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.d.cts CHANGED
@@ -1160,6 +1160,18 @@ interface SessionRunReport {
1160
1160
  presentations: CardPresentation[];
1161
1161
  queueSnapshots: QueueSnapshot[];
1162
1162
  }
1163
+ /**
1164
+ * Release pipeline run-history / SRS backlog debug memory from the previous
1165
+ * session before this session begins piling new runs on top of it. Must be
1166
+ * called before the first pipeline run of the new session (including the
1167
+ * bootstrap run in prepareSession) — clearing on session START rather than
1168
+ * END keeps post-session inspection, the dominant debugging workflow, fully
1169
+ * functional: a finished session's run history sits intact until the user
1170
+ * actually begins another one. It's a separate call from startSessionTracking
1171
+ * because that function can't run until supplyQ/failedQ are populated by the
1172
+ * bootstrap pipeline run, which would otherwise be cleared out from under it.
1173
+ */
1174
+ declare function clearStaleSessionDebugState(): void;
1163
1175
  /**
1164
1176
  * Start tracking a new session.
1165
1177
  */
@@ -1467,4 +1479,4 @@ interface CouchDbUserDoc extends PouchDB.Authentication.User {
1467
1479
  entitlements: UserEntitlements;
1468
1480
  }
1469
1481
 
1470
- export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, type CardPresentation, CardRecord, type CouchDbUserDoc, CourseDBInterface, CourseLookup, CourseRegistrationDoc, type CustomQuestionsData, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, GeneratorResult, Loggable, type MigrationOptions, type MigrationResult, type MixerCardInfo, type MixerRunReport, NOT_SET, type OutcomeObserver, type ProcessedDataShape, type ProcessedQuestionData, QuestionRecord, type QueueSnapshot, QuotaRoundRobinMixer, ReplanHints, type ReplanOptions, type ResponseResult, type RestoreProgress, type SessionAction, SessionController, type SessionControls, type SessionOutcome, type SessionRunReport, type SourceBatch, type SourceMixer, type SourceSelectionBreakdown, type SourceSummary, SrsBacklogDebug, StaticCourseManifest, type StaticCourseValidation, StaticToCouchDBMigrator, StudyContentSource, StudySessionItem, type StudySessionRecord, TagFilteredContentSource, type UserAccountStatus, UserDBInterface, type UserEntitlements, type ValidationIssue, type ValidationResult, WeightedCard, _resetDataLayer, captureMixerRun, endSessionTracking, ensureAppDataDirectory, getAppDataDirectory, getDataLayer, getDbPath, initializeDataDirectory, initializeDataLayer, isDataShapeRegistered, isDataShapeSchemaAvailable, isQuestionTypeRegistered, mixerDebugAPI, mountMixerDebugger, mountSessionDebugger, processCustomQuestionsData, recordCardPresentation, registerBlanksCard, registerCustomQuestionTypes, registerDataShape, registerQuestionType, registerSeedData, removeCustomQuestionTypes, removeDataShape, removeQuestionType, sessionDebugAPI, snapshotQueues, startSessionTracking, validateMigration, validateStaticCourse };
1482
+ export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, type CardPresentation, CardRecord, type CouchDbUserDoc, CourseDBInterface, CourseLookup, CourseRegistrationDoc, type CustomQuestionsData, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, GeneratorResult, Loggable, type MigrationOptions, type MigrationResult, type MixerCardInfo, type MixerRunReport, NOT_SET, type OutcomeObserver, type ProcessedDataShape, type ProcessedQuestionData, QuestionRecord, type QueueSnapshot, QuotaRoundRobinMixer, ReplanHints, type ReplanOptions, type ResponseResult, type RestoreProgress, type SessionAction, SessionController, type SessionControls, type SessionOutcome, type SessionRunReport, type SourceBatch, type SourceMixer, type SourceSelectionBreakdown, type SourceSummary, SrsBacklogDebug, StaticCourseManifest, type StaticCourseValidation, StaticToCouchDBMigrator, StudyContentSource, StudySessionItem, type StudySessionRecord, TagFilteredContentSource, type UserAccountStatus, UserDBInterface, type UserEntitlements, type ValidationIssue, type ValidationResult, WeightedCard, _resetDataLayer, captureMixerRun, clearStaleSessionDebugState, endSessionTracking, ensureAppDataDirectory, getAppDataDirectory, getDataLayer, getDbPath, initializeDataDirectory, initializeDataLayer, isDataShapeRegistered, isDataShapeSchemaAvailable, isQuestionTypeRegistered, mixerDebugAPI, mountMixerDebugger, mountSessionDebugger, processCustomQuestionsData, recordCardPresentation, registerBlanksCard, registerCustomQuestionTypes, registerDataShape, registerQuestionType, registerSeedData, removeCustomQuestionTypes, removeDataShape, removeQuestionType, sessionDebugAPI, snapshotQueues, startSessionTracking, validateMigration, validateStaticCourse };
package/dist/index.d.ts CHANGED
@@ -1160,6 +1160,18 @@ interface SessionRunReport {
1160
1160
  presentations: CardPresentation[];
1161
1161
  queueSnapshots: QueueSnapshot[];
1162
1162
  }
1163
+ /**
1164
+ * Release pipeline run-history / SRS backlog debug memory from the previous
1165
+ * session before this session begins piling new runs on top of it. Must be
1166
+ * called before the first pipeline run of the new session (including the
1167
+ * bootstrap run in prepareSession) — clearing on session START rather than
1168
+ * END keeps post-session inspection, the dominant debugging workflow, fully
1169
+ * functional: a finished session's run history sits intact until the user
1170
+ * actually begins another one. It's a separate call from startSessionTracking
1171
+ * because that function can't run until supplyQ/failedQ are populated by the
1172
+ * bootstrap pipeline run, which would otherwise be cleared out from under it.
1173
+ */
1174
+ declare function clearStaleSessionDebugState(): void;
1163
1175
  /**
1164
1176
  * Start tracking a new session.
1165
1177
  */
@@ -1467,4 +1479,4 @@ interface CouchDbUserDoc extends PouchDB.Authentication.User {
1467
1479
  entitlements: UserEntitlements;
1468
1480
  }
1469
1481
 
1470
- export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, type CardPresentation, CardRecord, type CouchDbUserDoc, CourseDBInterface, CourseLookup, CourseRegistrationDoc, type CustomQuestionsData, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, GeneratorResult, Loggable, type MigrationOptions, type MigrationResult, type MixerCardInfo, type MixerRunReport, NOT_SET, type OutcomeObserver, type ProcessedDataShape, type ProcessedQuestionData, QuestionRecord, type QueueSnapshot, QuotaRoundRobinMixer, ReplanHints, type ReplanOptions, type ResponseResult, type RestoreProgress, type SessionAction, SessionController, type SessionControls, type SessionOutcome, type SessionRunReport, type SourceBatch, type SourceMixer, type SourceSelectionBreakdown, type SourceSummary, SrsBacklogDebug, StaticCourseManifest, type StaticCourseValidation, StaticToCouchDBMigrator, StudyContentSource, StudySessionItem, type StudySessionRecord, TagFilteredContentSource, type UserAccountStatus, UserDBInterface, type UserEntitlements, type ValidationIssue, type ValidationResult, WeightedCard, _resetDataLayer, captureMixerRun, endSessionTracking, ensureAppDataDirectory, getAppDataDirectory, getDataLayer, getDbPath, initializeDataDirectory, initializeDataLayer, isDataShapeRegistered, isDataShapeSchemaAvailable, isQuestionTypeRegistered, mixerDebugAPI, mountMixerDebugger, mountSessionDebugger, processCustomQuestionsData, recordCardPresentation, registerBlanksCard, registerCustomQuestionTypes, registerDataShape, registerQuestionType, registerSeedData, removeCustomQuestionTypes, removeDataShape, removeQuestionType, sessionDebugAPI, snapshotQueues, startSessionTracking, validateMigration, validateStaticCourse };
1482
+ export { type AggregatedDocument, type AttachmentUploadResult, CardHistory, type CardPresentation, CardRecord, type CouchDbUserDoc, CourseDBInterface, CourseLookup, CourseRegistrationDoc, type CustomQuestionsData, DEFAULT_MIGRATION_OPTIONS, type DataLayerConfig, DataLayerProvider, type DocumentCounts, ENV, type Entitlement, FileSystemAdapter, GeneratorResult, Loggable, type MigrationOptions, type MigrationResult, type MixerCardInfo, type MixerRunReport, NOT_SET, type OutcomeObserver, type ProcessedDataShape, type ProcessedQuestionData, QuestionRecord, type QueueSnapshot, QuotaRoundRobinMixer, ReplanHints, type ReplanOptions, type ResponseResult, type RestoreProgress, type SessionAction, SessionController, type SessionControls, type SessionOutcome, type SessionRunReport, type SourceBatch, type SourceMixer, type SourceSelectionBreakdown, type SourceSummary, SrsBacklogDebug, StaticCourseManifest, type StaticCourseValidation, StaticToCouchDBMigrator, StudyContentSource, StudySessionItem, type StudySessionRecord, TagFilteredContentSource, type UserAccountStatus, UserDBInterface, type UserEntitlements, type ValidationIssue, type ValidationResult, WeightedCard, _resetDataLayer, captureMixerRun, clearStaleSessionDebugState, endSessionTracking, ensureAppDataDirectory, getAppDataDirectory, getDataLayer, getDbPath, initializeDataDirectory, initializeDataLayer, isDataShapeRegistered, isDataShapeSchemaAvailable, isQuestionTypeRegistered, mixerDebugAPI, mountMixerDebugger, mountSessionDebugger, processCustomQuestionsData, recordCardPresentation, registerBlanksCard, registerCustomQuestionTypes, registerDataShape, registerQuestionType, registerSeedData, removeCustomQuestionTypes, removeDataShape, removeQuestionType, sessionDebugAPI, snapshotQueues, startSessionTracking, validateMigration, validateStaticCourse };
package/dist/index.js CHANGED
@@ -2918,7 +2918,7 @@ var srs_exports = {};
2918
2918
  __export(srs_exports, {
2919
2919
  default: () => SRSNavigator
2920
2920
  });
2921
- var import_moment3, DEFAULT_HEALTHY_BACKLOG, MAX_BACKLOG_MULTIPLIER, SRSNavigator;
2921
+ var import_moment3, DEFAULT_HEALTHY_BACKLOG, BACKLOG_GROWTH_RATE, SRSNavigator;
2922
2922
  var init_srs = __esm({
2923
2923
  "src/core/navigators/generators/srs.ts"() {
2924
2924
  "use strict";
@@ -2927,7 +2927,7 @@ var init_srs = __esm({
2927
2927
  init_SrsDebugger();
2928
2928
  init_logger();
2929
2929
  DEFAULT_HEALTHY_BACKLOG = 20;
2930
- MAX_BACKLOG_MULTIPLIER = 2;
2930
+ BACKLOG_GROWTH_RATE = 2;
2931
2931
  SRSNavigator = class extends ContentNavigator {
2932
2932
  /** Human-readable name for CardGenerator interface */
2933
2933
  name;
@@ -3049,7 +3049,7 @@ var init_srs = __esm({
3049
3049
  dueNow: dueReviews.length,
3050
3050
  healthyBacklog: this.healthyBacklog,
3051
3051
  backlogMultiplier,
3052
- maxBacklogMultiplier: MAX_BACKLOG_MULTIPLIER,
3052
+ backlogGrowthRate: BACKLOG_GROWTH_RATE,
3053
3053
  topReviewScore: sorted.length > 0 ? sorted[0].score : null,
3054
3054
  nextDueIn,
3055
3055
  timestamp: Date.now()
@@ -3059,25 +3059,30 @@ var init_srs = __esm({
3059
3059
  /**
3060
3060
  * Compute the multiplicative backlog pressure based on number of due reviews.
3061
3061
  *
3062
- * ×1.0 at or below the healthy threshold (no boost), increasing linearly above
3063
- * it and maxing out at MAX_BACKLOG_MULTIPLIER at the healthy backlog.
3062
+ * ×1.0 at or below the healthy threshold (no boost); above it, grows as
3063
+ * BACKLOG_GROWTH_RATE raised to the excess expressed in multiples of the
3064
+ * healthy threshold. Uncapped — self-regulating instead: reviews winning
3065
+ * slots depletes dueCount, which drops the ratio and relaxes the multiplier
3066
+ * next run.
3064
3067
  *
3065
- * Examples (with default healthyBacklog=20, MAX_BACKLOG_MULTIPLIER=2.0):
3066
- * - 10 due reviews → ×1.00 (healthy)
3067
- * - 20 due reviews → ×1.00 (at threshold)
3068
- * - 40 due reviews → ×1.50 (2x threshold)
3069
- * - 60 due reviews → ×2.00 (3x threshold, maxed)
3068
+ * Examples (with default healthyBacklog=20, BACKLOG_GROWTH_RATE=1.5):
3069
+ * - 10 due reviews → ×1.00 (healthy)
3070
+ * - 20 due reviews → ×1.00 (at threshold, ratio 0)
3071
+ * - 40 due reviews → ×1.50 (ratio 1, 2x threshold)
3072
+ * - 60 due reviews → ×2.25 (ratio 2, 3x threshold — old hard cap was ×2.00 here)
3073
+ * - 100 due reviews → ×5.06 (ratio 4, 5x threshold)
3074
+ * - 160 due reviews → ×17.09 (ratio 7, 8x threshold)
3070
3075
  *
3071
3076
  * @param dueCount - Number of reviews currently due
3072
- * @returns Multiplier applied to review urgency (1.0 to MAX_BACKLOG_MULTIPLIER)
3077
+ * @returns Multiplier applied to review urgency (>= 1.0, unbounded)
3073
3078
  */
3074
3079
  computeBacklogMultiplier(dueCount) {
3075
3080
  if (dueCount <= this.healthyBacklog) {
3076
3081
  return 1;
3077
3082
  }
3078
3083
  const excess = dueCount - this.healthyBacklog;
3079
- const multiplier = 1 + excess / this.healthyBacklog * ((MAX_BACKLOG_MULTIPLIER - 1) / 2);
3080
- return Math.min(MAX_BACKLOG_MULTIPLIER, multiplier);
3084
+ const ratio = excess / this.healthyBacklog;
3085
+ return Math.pow(BACKLOG_GROWTH_RATE, ratio);
3081
3086
  }
3082
3087
  /**
3083
3088
  * Compute urgency score for a review card.
@@ -3093,17 +3098,17 @@ var init_srs = __esm({
3093
3098
  * - 180 days → ~0.30
3094
3099
  *
3095
3100
  * 3. Backlog pressure = global *multiplier* when review backlog exceeds the
3096
- * healthy threshold (×1.0 healthy → up to MAX_BACKLOG_MULTIPLIER at ).
3101
+ * healthy threshold (×1.0 healthy → exponential growth, uncapped, above it).
3097
3102
  *
3098
3103
  * Combined: (base 0.5 + urgency factors * 0.45) × backlog multiplier.
3099
3104
  * Per-card range before pressure: ~0.57–0.95. NOT clamped to 1.0 — under a
3100
3105
  * heavy backlog reviews scale onto the open scale to compete with (and exceed)
3101
- * new cards; what keeps them from running away is the bounded multiplier, not
3102
- * a hard ceiling.
3106
+ * new cards; there's no ceiling at all now, so a bad enough backlog always
3107
+ * wins eventually — self-regulating because winning slots depletes dueCount.
3103
3108
  *
3104
3109
  * @param review - The scheduled card to score
3105
3110
  * @param now - Current time
3106
- * @param backlogMultiplier - Pre-computed backlog multiplier (1.0 to MAX_BACKLOG_MULTIPLIER)
3111
+ * @param backlogMultiplier - Pre-computed backlog multiplier (>= 1.0, unbounded)
3107
3112
  */
3108
3113
  computeUrgencyScore(review, now, backlogMultiplier) {
3109
3114
  const scheduledAt = import_moment3.default.utc(review.scheduledAt);
@@ -7412,6 +7417,14 @@ var init_CouchDBSyncStrategy = __esm({
7412
7417
  } else {
7413
7418
  logger.info("No documents to migrate from funnel account");
7414
7419
  }
7420
+ try {
7421
+ await oldLocalDB.destroy();
7422
+ logger.info(`Destroyed consumed guest DB for ${oldUsername}`);
7423
+ } catch (destroyErr) {
7424
+ logger.warn(
7425
+ `Failed to destroy consumed guest DB for ${oldUsername} (non-fatal): ${destroyErr instanceof Error ? destroyErr.message : String(destroyErr)}`
7426
+ );
7427
+ }
7415
7428
  return { success: true };
7416
7429
  } catch (error) {
7417
7430
  logger.error("Migration failed:", error);
@@ -7843,6 +7856,11 @@ Currently logged-in as ${this._username}.`
7843
7856
  return { ok: true };
7844
7857
  }
7845
7858
  const ret = await this.syncStrategy.logout();
7859
+ try {
7860
+ localStorage.removeItem("sk-guest-uuid");
7861
+ } catch (e) {
7862
+ logger.warn("localStorage not available (Node.js environment):", e);
7863
+ }
7846
7864
  this._username = await this.syncStrategy.getCurrentUsername();
7847
7865
  await this.init();
7848
7866
  return ret;
@@ -10568,6 +10586,7 @@ __export(index_exports, {
10568
10586
  buildStrategyStateId: () => buildStrategyStateId,
10569
10587
  captureMixerRun: () => captureMixerRun,
10570
10588
  clearSrsBacklogDebug: () => clearSrsBacklogDebug,
10589
+ clearStaleSessionDebugState: () => clearStaleSessionDebugState,
10571
10590
  computeDeviation: () => computeDeviation,
10572
10591
  computeEffectiveWeight: () => computeEffectiveWeight,
10573
10592
  computeOutcomeSignal: () => computeOutcomeSignal,
@@ -13737,12 +13756,12 @@ function hintsHtml(h) {
13737
13756
  function backlogHtml(backlog) {
13738
13757
  if (!backlog.length) return "";
13739
13758
  const rows = backlog.map((b) => {
13740
- const maxed = b.backlogMultiplier >= b.maxBacklogMultiplier - 1e-9;
13741
- const multColor = b.backlogMultiplier <= 1 ? "#86efac" : maxed ? "#fca5a5" : "#fcd34d";
13742
- const headroom = maxed ? "maxed \u2014 boosts decide order until they relax" : b.backlogMultiplier > 1 ? "climbing as backlog grows" : "healthy \u2014 no pressure";
13759
+ const hot = b.backlogMultiplier >= 3;
13760
+ const multColor = b.backlogMultiplier <= 1 ? "#86efac" : hot ? "#fca5a5" : "#fcd34d";
13761
+ const headroom = b.backlogMultiplier > 1 ? `climbing (\xD7${b.backlogGrowthRate.toFixed(2)} per ${b.healthyBacklog}-review excess, unbounded)` : "healthy \u2014 no pressure";
13743
13762
  const top = b.topReviewScore !== null ? b.topReviewScore.toFixed(2) : "\u2014";
13744
13763
  const next = b.nextDueIn ? ` <span style="opacity:.6">\xB7 next due ${esc(b.nextDueIn)}</span>` : "";
13745
- 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>`;
13764
+ 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>`;
13746
13765
  }).join("");
13747
13766
  return `<div style="margin-bottom:6px"><div style="color:#93c5fd">review backpressure</div>${rows}</div>`;
13748
13767
  }
@@ -13838,12 +13857,11 @@ function snapshotToText(s) {
13838
13857
  lines.push("");
13839
13858
  lines.push("review backpressure:");
13840
13859
  for (const b of s.reviewBacklog) {
13841
- const maxed = b.backlogMultiplier >= b.maxBacklogMultiplier - 1e-9;
13842
- const headroom = maxed ? "maxed (boosts decide order)" : b.backlogMultiplier > 1 ? "climbing" : "healthy";
13860
+ const headroom = b.backlogMultiplier > 1 ? "climbing" : "healthy";
13843
13861
  const top = b.topReviewScore !== null ? b.topReviewScore.toFixed(2) : "\u2014";
13844
13862
  const next = b.nextDueIn ? `, next due ${b.nextDueIn}` : "";
13845
13863
  lines.push(
13846
- ` ${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}`
13864
+ ` ${b.courseId.slice(0, 8)}: due ${b.dueNow}/${b.scheduledTotal} (healthy ${b.healthyBacklog})${next}; pressure \xD7${b.backlogMultiplier.toFixed(2)} ${headroom}; top review ${top}`
13847
13865
  );
13848
13866
  }
13849
13867
  }
@@ -13881,9 +13899,11 @@ function esc(value) {
13881
13899
  var activeSession = null;
13882
13900
  var sessionHistory = [];
13883
13901
  var MAX_HISTORY = 5;
13884
- function startSessionTracking(supplyQLength, failedQLength) {
13902
+ function clearStaleSessionDebugState() {
13885
13903
  clearRunHistory();
13886
13904
  clearSrsBacklogDebug();
13905
+ }
13906
+ function startSessionTracking(supplyQLength, failedQLength) {
13887
13907
  const sessionId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
13888
13908
  activeSession = {
13889
13909
  sessionId,
@@ -14365,6 +14385,7 @@ var SessionController = class _SessionController extends Loggable {
14365
14385
  "[SessionController] All content sources must implement getWeightedCards()."
14366
14386
  );
14367
14387
  }
14388
+ clearStaleSessionDebugState();
14368
14389
  const wellIndicated = await this.getWeightedContent();
14369
14390
  this._wellIndicatedRemaining = wellIndicated;
14370
14391
  if (wellIndicated >= 0 && wellIndicated < _SessionController.MIN_WELL_INDICATED) {
@@ -15269,6 +15290,7 @@ init_factory();
15269
15290
  buildStrategyStateId,
15270
15291
  captureMixerRun,
15271
15292
  clearSrsBacklogDebug,
15293
+ clearStaleSessionDebugState,
15272
15294
  computeDeviation,
15273
15295
  computeEffectiveWeight,
15274
15296
  computeOutcomeSignal,