@vue-skuilder/db 0.2.16 → 0.2.18

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.
Files changed (44) hide show
  1. package/dist/{SyncStrategy-CyATpyLQ.d.cts → SyncStrategy-BJMZq3WO.d.cts} +17 -0
  2. package/dist/{SyncStrategy-CyATpyLQ.d.ts → SyncStrategy-BJMZq3WO.d.ts} +17 -0
  3. package/dist/{contentSource-Brz42x7n.d.cts → contentSource-CBqZCoGU.d.cts} +85 -1
  4. package/dist/{contentSource-B1p-vdz7.d.ts → contentSource-CudEz5Tm.d.ts} +85 -1
  5. package/dist/core/index.d.cts +51 -4
  6. package/dist/core/index.d.ts +51 -4
  7. package/dist/core/index.js +258 -7
  8. package/dist/core/index.js.map +1 -1
  9. package/dist/core/index.mjs +254 -7
  10. package/dist/core/index.mjs.map +1 -1
  11. package/dist/{dataLayerProvider-CpwpT1rM.d.cts → dataLayerProvider-BBA8tJNx.d.cts} +1 -1
  12. package/dist/{dataLayerProvider-BWayUIoK.d.ts → dataLayerProvider-C9WgkBzR.d.ts} +1 -1
  13. package/dist/impl/couch/index.d.cts +16 -3
  14. package/dist/impl/couch/index.d.ts +16 -3
  15. package/dist/impl/couch/index.js +284 -9
  16. package/dist/impl/couch/index.js.map +1 -1
  17. package/dist/impl/couch/index.mjs +284 -9
  18. package/dist/impl/couch/index.mjs.map +1 -1
  19. package/dist/impl/static/index.d.cts +3 -3
  20. package/dist/impl/static/index.d.ts +3 -3
  21. package/dist/impl/static/index.js +250 -7
  22. package/dist/impl/static/index.js.map +1 -1
  23. package/dist/impl/static/index.mjs +250 -7
  24. package/dist/impl/static/index.mjs.map +1 -1
  25. package/dist/index.d.cts +8 -6
  26. package/dist/index.d.ts +8 -6
  27. package/dist/index.js +354 -10
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +350 -10
  30. package/dist/index.mjs.map +1 -1
  31. package/package.json +4 -3
  32. package/src/core/index.ts +1 -0
  33. package/src/core/interfaces/userDB.ts +11 -0
  34. package/src/core/navigators/StrategyPressureDebugger.ts +76 -0
  35. package/src/core/navigators/generators/prescribed.ts +122 -7
  36. package/src/core/navigators/index.ts +12 -0
  37. package/src/core/types/hydration.ts +78 -0
  38. package/src/impl/common/BaseUserDB.ts +202 -2
  39. package/src/impl/common/SyncStrategy.ts +19 -0
  40. package/src/impl/couch/CouchDBSyncStrategy.ts +54 -4
  41. package/src/study/SessionController.ts +7 -1
  42. package/src/study/SessionDebugger.ts +2 -0
  43. package/src/study/SessionOverlay.ts +113 -0
  44. package/tests/impl/hydration.test.ts +281 -0
@@ -36,6 +36,23 @@ interface SyncStrategy {
36
36
  * @returns PouchDB database instance for write operations
37
37
  */
38
38
  getWriteDB?(username: string): PouchDB.Database;
39
+ /**
40
+ * Pull the remote database into the local one and RESOLVE WHEN DONE.
41
+ *
42
+ * Distinct from startSync(): this is a one-shot, awaitable catch-up used to
43
+ * populate an empty local mirror before the user object is handed out. A
44
+ * strategy that omits it declares that it has no remote worth waiting for.
45
+ *
46
+ * Mechanism only — BaseUser owns the policy (whether to run it, timeout,
47
+ * marker bookkeeping, resulting hydration state).
48
+ *
49
+ * @param localDB The local PouchDB instance
50
+ * @param remoteDB The remote PouchDB instance
51
+ * @returns Count of documents written locally
52
+ */
53
+ hydrate?(localDB: PouchDB.Database, remoteDB: PouchDB.Database): Promise<{
54
+ docsWritten: number;
55
+ }>;
39
56
  /**
40
57
  * Start synchronization between local and remote databases
41
58
  * @param localDB The local PouchDB instance
@@ -36,6 +36,23 @@ interface SyncStrategy {
36
36
  * @returns PouchDB database instance for write operations
37
37
  */
38
38
  getWriteDB?(username: string): PouchDB.Database;
39
+ /**
40
+ * Pull the remote database into the local one and RESOLVE WHEN DONE.
41
+ *
42
+ * Distinct from startSync(): this is a one-shot, awaitable catch-up used to
43
+ * populate an empty local mirror before the user object is handed out. A
44
+ * strategy that omits it declares that it has no remote worth waiting for.
45
+ *
46
+ * Mechanism only — BaseUser owns the policy (whether to run it, timeout,
47
+ * marker bookkeeping, resulting hydration state).
48
+ *
49
+ * @param localDB The local PouchDB instance
50
+ * @param remoteDB The remote PouchDB instance
51
+ * @returns Count of documents written locally
52
+ */
53
+ hydrate?(localDB: PouchDB.Database, remoteDB: PouchDB.Database): Promise<{
54
+ docsWritten: number;
55
+ }>;
39
56
  /**
40
57
  * Start synchronization between local and remote databases
41
58
  * @param localDB The local PouchDB instance
@@ -418,6 +418,81 @@ interface UserOutcomeRecord {
418
418
  };
419
419
  }
420
420
 
421
+ /**
422
+ * User database hydration.
423
+ *
424
+ * A logged-in user's data lives in a remote CouchDB `userdb-<hex>` and is
425
+ * mirrored into a browser-local PouchDB. On a device that has never synced
426
+ * that account, the local mirror starts EMPTY — and every local read
427
+ * (`getStrategyState`, `getConfig`, `getCourseRegistrationsDoc`, ...) answers
428
+ * "no such document", which is indistinguishable from "brand new user".
429
+ *
430
+ * Consumers acting on that answer render a new-user experience to an existing
431
+ * user, and — worse — compute writes from empty state that then lose to the
432
+ * real remote document at replication time. Hydration closes that window by
433
+ * pulling the account's documents down BEFORE the user object is handed out.
434
+ */
435
+ /**
436
+ * Where a user's local database stands relative to its remote counterpart.
437
+ *
438
+ * Only `failed` is a blocking condition. `stale` explicitly is not: it means a
439
+ * full pull completed on this device previously, so local data is real and
440
+ * merely possibly-behind — live sync closes the gap in the background. That is
441
+ * the ordinary offline case and it must keep working.
442
+ */
443
+ type UserHydrationState =
444
+ /** Guest, or a data layer with no remote. There is nothing to hydrate from. */
445
+ 'not-required'
446
+ /** Initial pull in flight. */
447
+ | 'hydrating'
448
+ /** Initial pull completed this session. Local is a faithful mirror. */
449
+ | 'hydrated'
450
+ /**
451
+ * A previous session completed a full pull on this device (recorded by the
452
+ * `_local/hydration` marker). Local data is real; live sync is catching up.
453
+ */
454
+ | 'stale'
455
+ /**
456
+ * No pull has ever completed on this device and one could not be completed
457
+ * now. Local reads CANNOT be trusted to mean "no data" — callers must not
458
+ * present a new-user experience or compute writes from what they read.
459
+ */
460
+ | 'failed';
461
+ /**
462
+ * Hydration state plus observability detail.
463
+ *
464
+ * Shaped to mirror `CourseSyncStatus` in CourseSyncService, which solves the
465
+ * same problem for course databases.
466
+ */
467
+ interface UserHydrationStatus {
468
+ state: UserHydrationState;
469
+ /** Documents pulled by the initial replication (set when state is `hydrated`). */
470
+ docsWritten?: number;
471
+ /** Wall-clock duration of the initial pull attempt, successful or not. */
472
+ durationMs?: number;
473
+ /** Failure detail, set when state is `failed`. */
474
+ error?: string;
475
+ }
476
+ /**
477
+ * ID of the per-device marker recording that a full pull once completed.
478
+ *
479
+ * `_local/*` documents are deliberately excluded from replication by CouchDB
480
+ * and PouchDB alike, which is exactly the semantics wanted here: the marker
481
+ * describes THIS device's mirror, and must never travel to another one.
482
+ */
483
+ declare const HYDRATION_MARKER_ID = "_local/hydration";
484
+ /**
485
+ * Payload of {@link HYDRATION_MARKER_ID}.
486
+ */
487
+ interface HydrationMarker {
488
+ _id: typeof HYDRATION_MARKER_ID;
489
+ _rev?: string;
490
+ /** Account the mirror was hydrated for — guards against a stale marker after an account switch. */
491
+ username: string;
492
+ /** ISO timestamp of the most recent successful full pull. */
493
+ hydratedAt: string;
494
+ }
495
+
421
496
  type Update<T> = Partial<T> | ((x: T) => T);
422
497
 
423
498
  interface DocumentUpdater {
@@ -438,6 +513,15 @@ interface UserDBReader {
438
513
  get<T>(id: string): Promise<T & PouchDB.Core.RevisionIdMeta>;
439
514
  getUsername(): string;
440
515
  isLoggedIn(): boolean;
516
+ /**
517
+ * How far this device's local mirror of the user's data can be trusted.
518
+ *
519
+ * Reads answer from the local mirror, so on a device that has never synced
520
+ * this account "document not found" does not mean "no such data". Anything
521
+ * that would otherwise interpret an empty read as a new user should check
522
+ * for `failed` first. See {@link UserHydrationStatus}.
523
+ */
524
+ hydrationStatus(): UserHydrationStatus;
441
525
  /**
442
526
  * Get user configuration
443
527
  */
@@ -1248,4 +1332,4 @@ interface StudyContentSource {
1248
1332
  }
1249
1333
  declare function getStudySource(source: ContentSourceID, user: UserDBInterface): Promise<StudyContentSource>;
1250
1334
 
1251
- export { Navigators as $, type AdminDBInterface as A, type UsrCrsDataInterface as B, type CourseDBInterface as C, type DataLayerResult as D, type ClassroomRegistrationDesignation as E, type ClassroomRegistration as F, type GeneratorResult as G, type ClassroomRegistrationDoc as H, type SessionTrackingData as I, type UserConfig as J, type ActivityRecord as K, type CourseRegistration as L, type UserOutcomeRecord as M, type NavigatorConstructor as N, registerNavigator as O, getRegisteredNavigator as P, hasRegisteredNavigator as Q, type ReplanHints as R, type StudySessionItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, getRegisteredNavigatorRole as V, type WeightedCard as W, getRegisteredNavigatorNames as X, initializeNavigatorRegistry as Y, type StrategyContribution as Z, getCardOrigin as _, type UserDBReader as a, NavigatorRole as a0, NavigatorRoles as a1, isGenerator as a2, isFilter as a3, type CardGenerator as a4, type GeneratorContext as a5, type CardGeneratorFactory as a6, type LearnableWeight as a7, type OrchestrationContext as a8, computeDeviation as a9, computeSpread as aa, computeEffectiveWeight as ab, createOrchestrationContext as ac, type DocumentUpdater as ad, newInterval as ae, type CoursesDBInterface as b, type ClassroomDBInterface as c, type CourseInfo as d, type ContentNavigationStrategyData as e, ContentNavigator as f, type AssignedContent as g, type StudyContentSource as h, type StudentClassroomDBInterface as i, type ScheduledCard as j, type StudySessionFailedItem as k, type StudySessionFailedNewItem as l, type StudySessionFailedReviewItem as m, type StudySessionNewItem as n, type StudySessionReviewItem as o, isReview as p, type ContentSourceID as q, getStudySource as r, type CourseRegistrationDoc as s, type AssignedTag as t, type AssignedCourse as u, type AssignedCard as v, type UserDBWriter as w, type UserDBAuthenticator as x, type UserCourseSettings as y, type UserCourseSetting as z };
1335
+ export { getRegisteredNavigatorNames as $, type AdminDBInterface as A, type UsrCrsDataInterface as B, type CourseDBInterface as C, type DataLayerResult as D, type ClassroomRegistrationDesignation as E, type ClassroomRegistration as F, type GeneratorResult as G, type ClassroomRegistrationDoc as H, type SessionTrackingData as I, type UserConfig as J, type ActivityRecord as K, type CourseRegistration as L, type UserOutcomeRecord as M, type UserHydrationState as N, type UserHydrationStatus as O, HYDRATION_MARKER_ID as P, type HydrationMarker as Q, type ReplanHints as R, type StudySessionItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, type NavigatorConstructor as V, type WeightedCard as W, registerNavigator as X, getRegisteredNavigator as Y, hasRegisteredNavigator as Z, getRegisteredNavigatorRole as _, type UserDBReader as a, initializeNavigatorRegistry as a0, type StrategyContribution as a1, getCardOrigin as a2, Navigators as a3, NavigatorRole as a4, NavigatorRoles as a5, isGenerator as a6, isFilter as a7, type CardGenerator as a8, type GeneratorContext as a9, type CardGeneratorFactory as aa, type LearnableWeight as ab, type OrchestrationContext as ac, computeDeviation as ad, computeSpread as ae, computeEffectiveWeight as af, createOrchestrationContext as ag, type DocumentUpdater as ah, newInterval as ai, type CoursesDBInterface as b, type ClassroomDBInterface as c, type CourseInfo as d, type ContentNavigationStrategyData as e, ContentNavigator as f, type AssignedContent as g, type StudyContentSource as h, type StudentClassroomDBInterface as i, type ScheduledCard as j, type StudySessionFailedItem as k, type StudySessionFailedNewItem as l, type StudySessionFailedReviewItem as m, type StudySessionNewItem as n, type StudySessionReviewItem as o, isReview as p, type ContentSourceID as q, getStudySource as r, type CourseRegistrationDoc as s, type AssignedTag as t, type AssignedCourse as u, type AssignedCard as v, type UserDBWriter as w, type UserDBAuthenticator as x, type UserCourseSettings as y, type UserCourseSetting as z };
@@ -418,6 +418,81 @@ interface UserOutcomeRecord {
418
418
  };
419
419
  }
420
420
 
421
+ /**
422
+ * User database hydration.
423
+ *
424
+ * A logged-in user's data lives in a remote CouchDB `userdb-<hex>` and is
425
+ * mirrored into a browser-local PouchDB. On a device that has never synced
426
+ * that account, the local mirror starts EMPTY — and every local read
427
+ * (`getStrategyState`, `getConfig`, `getCourseRegistrationsDoc`, ...) answers
428
+ * "no such document", which is indistinguishable from "brand new user".
429
+ *
430
+ * Consumers acting on that answer render a new-user experience to an existing
431
+ * user, and — worse — compute writes from empty state that then lose to the
432
+ * real remote document at replication time. Hydration closes that window by
433
+ * pulling the account's documents down BEFORE the user object is handed out.
434
+ */
435
+ /**
436
+ * Where a user's local database stands relative to its remote counterpart.
437
+ *
438
+ * Only `failed` is a blocking condition. `stale` explicitly is not: it means a
439
+ * full pull completed on this device previously, so local data is real and
440
+ * merely possibly-behind — live sync closes the gap in the background. That is
441
+ * the ordinary offline case and it must keep working.
442
+ */
443
+ type UserHydrationState =
444
+ /** Guest, or a data layer with no remote. There is nothing to hydrate from. */
445
+ 'not-required'
446
+ /** Initial pull in flight. */
447
+ | 'hydrating'
448
+ /** Initial pull completed this session. Local is a faithful mirror. */
449
+ | 'hydrated'
450
+ /**
451
+ * A previous session completed a full pull on this device (recorded by the
452
+ * `_local/hydration` marker). Local data is real; live sync is catching up.
453
+ */
454
+ | 'stale'
455
+ /**
456
+ * No pull has ever completed on this device and one could not be completed
457
+ * now. Local reads CANNOT be trusted to mean "no data" — callers must not
458
+ * present a new-user experience or compute writes from what they read.
459
+ */
460
+ | 'failed';
461
+ /**
462
+ * Hydration state plus observability detail.
463
+ *
464
+ * Shaped to mirror `CourseSyncStatus` in CourseSyncService, which solves the
465
+ * same problem for course databases.
466
+ */
467
+ interface UserHydrationStatus {
468
+ state: UserHydrationState;
469
+ /** Documents pulled by the initial replication (set when state is `hydrated`). */
470
+ docsWritten?: number;
471
+ /** Wall-clock duration of the initial pull attempt, successful or not. */
472
+ durationMs?: number;
473
+ /** Failure detail, set when state is `failed`. */
474
+ error?: string;
475
+ }
476
+ /**
477
+ * ID of the per-device marker recording that a full pull once completed.
478
+ *
479
+ * `_local/*` documents are deliberately excluded from replication by CouchDB
480
+ * and PouchDB alike, which is exactly the semantics wanted here: the marker
481
+ * describes THIS device's mirror, and must never travel to another one.
482
+ */
483
+ declare const HYDRATION_MARKER_ID = "_local/hydration";
484
+ /**
485
+ * Payload of {@link HYDRATION_MARKER_ID}.
486
+ */
487
+ interface HydrationMarker {
488
+ _id: typeof HYDRATION_MARKER_ID;
489
+ _rev?: string;
490
+ /** Account the mirror was hydrated for — guards against a stale marker after an account switch. */
491
+ username: string;
492
+ /** ISO timestamp of the most recent successful full pull. */
493
+ hydratedAt: string;
494
+ }
495
+
421
496
  type Update<T> = Partial<T> | ((x: T) => T);
422
497
 
423
498
  interface DocumentUpdater {
@@ -438,6 +513,15 @@ interface UserDBReader {
438
513
  get<T>(id: string): Promise<T & PouchDB.Core.RevisionIdMeta>;
439
514
  getUsername(): string;
440
515
  isLoggedIn(): boolean;
516
+ /**
517
+ * How far this device's local mirror of the user's data can be trusted.
518
+ *
519
+ * Reads answer from the local mirror, so on a device that has never synced
520
+ * this account "document not found" does not mean "no such data". Anything
521
+ * that would otherwise interpret an empty read as a new user should check
522
+ * for `failed` first. See {@link UserHydrationStatus}.
523
+ */
524
+ hydrationStatus(): UserHydrationStatus;
441
525
  /**
442
526
  * Get user configuration
443
527
  */
@@ -1248,4 +1332,4 @@ interface StudyContentSource {
1248
1332
  }
1249
1333
  declare function getStudySource(source: ContentSourceID, user: UserDBInterface): Promise<StudyContentSource>;
1250
1334
 
1251
- export { Navigators as $, type AdminDBInterface as A, type UsrCrsDataInterface as B, type CourseDBInterface as C, type DataLayerResult as D, type ClassroomRegistrationDesignation as E, type ClassroomRegistration as F, type GeneratorResult as G, type ClassroomRegistrationDoc as H, type SessionTrackingData as I, type UserConfig as J, type ActivityRecord as K, type CourseRegistration as L, type UserOutcomeRecord as M, type NavigatorConstructor as N, registerNavigator as O, getRegisteredNavigator as P, hasRegisteredNavigator as Q, type ReplanHints as R, type StudySessionItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, getRegisteredNavigatorRole as V, type WeightedCard as W, getRegisteredNavigatorNames as X, initializeNavigatorRegistry as Y, type StrategyContribution as Z, getCardOrigin as _, type UserDBReader as a, NavigatorRole as a0, NavigatorRoles as a1, isGenerator as a2, isFilter as a3, type CardGenerator as a4, type GeneratorContext as a5, type CardGeneratorFactory as a6, type LearnableWeight as a7, type OrchestrationContext as a8, computeDeviation as a9, computeSpread as aa, computeEffectiveWeight as ab, createOrchestrationContext as ac, type DocumentUpdater as ad, newInterval as ae, type CoursesDBInterface as b, type ClassroomDBInterface as c, type CourseInfo as d, type ContentNavigationStrategyData as e, ContentNavigator as f, type AssignedContent as g, type StudyContentSource as h, type StudentClassroomDBInterface as i, type ScheduledCard as j, type StudySessionFailedItem as k, type StudySessionFailedNewItem as l, type StudySessionFailedReviewItem as m, type StudySessionNewItem as n, type StudySessionReviewItem as o, isReview as p, type ContentSourceID as q, getStudySource as r, type CourseRegistrationDoc as s, type AssignedTag as t, type AssignedCourse as u, type AssignedCard as v, type UserDBWriter as w, type UserDBAuthenticator as x, type UserCourseSettings as y, type UserCourseSetting as z };
1335
+ export { getRegisteredNavigatorNames as $, type AdminDBInterface as A, type UsrCrsDataInterface as B, type CourseDBInterface as C, type DataLayerResult as D, type ClassroomRegistrationDesignation as E, type ClassroomRegistration as F, type GeneratorResult as G, type ClassroomRegistrationDoc as H, type SessionTrackingData as I, type UserConfig as J, type ActivityRecord as K, type CourseRegistration as L, type UserOutcomeRecord as M, type UserHydrationState as N, type UserHydrationStatus as O, HYDRATION_MARKER_ID as P, type HydrationMarker as Q, type ReplanHints as R, type StudySessionItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, type NavigatorConstructor as V, type WeightedCard as W, registerNavigator as X, getRegisteredNavigator as Y, hasRegisteredNavigator as Z, getRegisteredNavigatorRole as _, type UserDBReader as a, initializeNavigatorRegistry as a0, type StrategyContribution as a1, getCardOrigin as a2, Navigators as a3, NavigatorRole as a4, NavigatorRoles as a5, isGenerator as a6, isFilter as a7, type CardGenerator as a8, type GeneratorContext as a9, type CardGeneratorFactory as aa, type LearnableWeight as ab, type OrchestrationContext as ac, computeDeviation as ad, computeSpread as ae, computeEffectiveWeight as af, createOrchestrationContext as ag, type DocumentUpdater as ah, newInterval as ai, type CoursesDBInterface as b, type ClassroomDBInterface as c, type CourseInfo as d, type ContentNavigationStrategyData as e, ContentNavigator as f, type AssignedContent as g, type StudyContentSource as h, type StudentClassroomDBInterface as i, type ScheduledCard as j, type StudySessionFailedItem as k, type StudySessionFailedNewItem as l, type StudySessionFailedReviewItem as m, type StudySessionNewItem as n, type StudySessionReviewItem as o, isReview as p, type ContentSourceID as q, getStudySource as r, type CourseRegistrationDoc as s, type AssignedTag as t, type AssignedCourse as u, type AssignedCard as v, type UserDBWriter as w, type UserDBAuthenticator as x, type UserCourseSettings as y, type UserCourseSetting as z };
@@ -1,6 +1,6 @@
1
- import { a7 as LearnableWeight, M as UserOutcomeRecord, a8 as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface, R as ReplanHints, Z as StrategyContribution } from '../contentSource-Brz42x7n.cjs';
2
- export { K as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, a4 as CardGenerator, a6 as CardGeneratorFactory, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, H as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, L as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, a5 as GeneratorContext, G as GeneratorResult, N as NavigatorConstructor, a0 as NavigatorRole, a1 as NavigatorRoles, $ as Navigators, j as ScheduledCard, I as SessionTrackingData, i as StudentClassroomDBInterface, h as StudyContentSource, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, S as StudySessionItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, J as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, a9 as computeDeviation, ab as computeEffectiveWeight, aa as computeSpread, ac as createOrchestrationContext, _ as getCardOrigin, P as getRegisteredNavigator, X as getRegisteredNavigatorNames, V as getRegisteredNavigatorRole, r as getStudySource, Q as hasRegisteredNavigator, Y as initializeNavigatorRegistry, a3 as isFilter, a2 as isGenerator, p as isReview, O as registerNavigator } from '../contentSource-Brz42x7n.cjs';
3
- export { D as DataLayerProvider } from '../dataLayerProvider-CpwpT1rM.cjs';
1
+ import { ab as LearnableWeight, M as UserOutcomeRecord, ac as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface, R as ReplanHints, a1 as StrategyContribution } from '../contentSource-CBqZCoGU.cjs';
2
+ export { K as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, a8 as CardGenerator, aa as CardGeneratorFactory, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, H as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, L as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, a9 as GeneratorContext, G as GeneratorResult, P as HYDRATION_MARKER_ID, Q as HydrationMarker, V as NavigatorConstructor, a4 as NavigatorRole, a5 as NavigatorRoles, a3 as Navigators, j as ScheduledCard, I as SessionTrackingData, i as StudentClassroomDBInterface, h as StudyContentSource, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, S as StudySessionItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, J as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, N as UserHydrationState, O as UserHydrationStatus, B as UsrCrsDataInterface, ad as computeDeviation, af as computeEffectiveWeight, ae as computeSpread, ag as createOrchestrationContext, a2 as getCardOrigin, Y as getRegisteredNavigator, $ as getRegisteredNavigatorNames, _ as getRegisteredNavigatorRole, r as getStudySource, Z as hasRegisteredNavigator, a0 as initializeNavigatorRegistry, a7 as isFilter, a6 as isGenerator, p as isReview, X as registerNavigator } from '../contentSource-CBqZCoGU.cjs';
3
+ export { D as DataLayerProvider } from '../dataLayerProvider-BBA8tJNx.cjs';
4
4
  import { D as DocType, d as QuestionRecord, b as DocTypePrefixes, C as CardHistory, c as CardRecord } from '../types-legacy-4tlwHnXo.cjs';
5
5
  export { e as CardData, f as CourseListData, h as DataShapeData, g as DisplayableData, F as Field, G as GuestUsername, Q as QualifiedCardID, i as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-4tlwHnXo.cjs';
6
6
  import { DataShape, ParsedCard } from '@vue-skuilder/common';
@@ -37,6 +37,53 @@ declare function getSrsBacklogDebug(): SrsBacklogDebug[];
37
37
  /** Drop all captured snapshots (called on session start, alongside pipeline history). */
38
38
  declare function clearSrsBacklogDebug(): void;
39
39
 
40
+ /**
41
+ * A single named pressure reading. The common shape across strategies: a
42
+ * multiplier that climbs under some accumulated condition (staleness, debt,
43
+ * blockage), optionally clamped at a cap.
44
+ */
45
+ interface PressureGaugeDebug {
46
+ /** Stable identifier within the source (e.g. 'group:intro-core:target'). */
47
+ id: string;
48
+ /** Short display label (e.g. 'intro-core targets'). */
49
+ label: string;
50
+ /** Current pressure multiplier (×1.0 = no pressure). */
51
+ multiplier: number;
52
+ /** Clamp ceiling, if the multiplier is capped. Omit for unbounded. */
53
+ max?: number;
54
+ /** One-line context for the reading (counts, mode, staleness). */
55
+ detail?: string;
56
+ /** Expandable rows (blocked target ids, per-tag debt ages, ...). */
57
+ items?: Array<{
58
+ label: string;
59
+ value?: string;
60
+ }>;
61
+ }
62
+ /** One strategy's pressure snapshot for one course, captured once per run. */
63
+ interface StrategyPressureDebug {
64
+ /** Producer identity — implementingClass name (e.g. 'prescribed'). */
65
+ source: string;
66
+ courseId: string;
67
+ gauges: PressureGaugeDebug[];
68
+ /**
69
+ * Highest score this strategy emitted into the candidate pool this run;
70
+ * null if it emitted nothing. Compare against the supplyQ head score to
71
+ * read how the pressure is competing for slots (same crossover read as the
72
+ * SRS panel's `top review`).
73
+ */
74
+ topScore?: number | null;
75
+ /** Label of any one-shot hints emitted alongside the cards this run. */
76
+ hintsLabel?: string;
77
+ /** Epoch ms of capture. */
78
+ timestamp: number;
79
+ }
80
+ /** Called by a strategy once per run. Latest snapshot per (source, course) wins. */
81
+ declare function captureStrategyPressure(snapshot: StrategyPressureDebug): void;
82
+ /** Current pressure snapshot for every source seen, newest-first. */
83
+ declare function getStrategyPressureDebug(): StrategyPressureDebug[];
84
+ /** Drop all captured snapshots (called on session start, alongside pipeline history). */
85
+ declare function clearStrategyPressureDebug(): void;
86
+
40
87
  /**
41
88
  * Snapshot of the learning state for a strategy.
42
89
  *
@@ -805,4 +852,4 @@ declare const userDBDebugAPI: {
805
852
  */
806
853
  declare function mountUserDBDebugger(): void;
807
854
 
808
- export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, CardHistory, CardRecord, CourseDBInterface, DIVERSITY_FLOOR, DIVERSITY_STRENGTH, type DiversityRerankOptions, DocType, DocTypePrefixes, type FilterContext, type FilterImpact, type GeneratorSummary, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, type PipelineForecaster, type PipelineRunReport, QuestionRecord, ReplanHints, type SignalConfig, type SrsBacklogDebug, StrategyContribution, type StrategyLearningState, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, clearSrsBacklogDebug, computeOutcomeSignal, computeStrategyGradient, diversityRerank, docIsDeleted, getActivePipeline, getCardHistoryID, getDefaultLearnableWeight, getSrsBacklogDebug, importParsedCards, isQuestionRecord, mountPipelineDebugger, mountUserDBDebugger, parseCardHistoryID, pipelineDebugAPI, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, userDBDebugAPI, validateProcessorConfig };
855
+ export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, CardHistory, CardRecord, CourseDBInterface, DIVERSITY_FLOOR, DIVERSITY_STRENGTH, type DiversityRerankOptions, DocType, DocTypePrefixes, type FilterContext, type FilterImpact, type GeneratorSummary, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, type PipelineForecaster, type PipelineRunReport, type PressureGaugeDebug, QuestionRecord, ReplanHints, type SignalConfig, type SrsBacklogDebug, StrategyContribution, type StrategyLearningState, type StrategyPressureDebug, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, captureStrategyPressure, clearSrsBacklogDebug, clearStrategyPressureDebug, computeOutcomeSignal, computeStrategyGradient, diversityRerank, docIsDeleted, getActivePipeline, getCardHistoryID, getDefaultLearnableWeight, getSrsBacklogDebug, getStrategyPressureDebug, importParsedCards, isQuestionRecord, mountPipelineDebugger, mountUserDBDebugger, parseCardHistoryID, pipelineDebugAPI, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, userDBDebugAPI, validateProcessorConfig };
@@ -1,6 +1,6 @@
1
- import { a7 as LearnableWeight, M as UserOutcomeRecord, a8 as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface, R as ReplanHints, Z as StrategyContribution } from '../contentSource-B1p-vdz7.js';
2
- export { K as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, a4 as CardGenerator, a6 as CardGeneratorFactory, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, H as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, L as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, a5 as GeneratorContext, G as GeneratorResult, N as NavigatorConstructor, a0 as NavigatorRole, a1 as NavigatorRoles, $ as Navigators, j as ScheduledCard, I as SessionTrackingData, i as StudentClassroomDBInterface, h as StudyContentSource, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, S as StudySessionItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, J as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, a9 as computeDeviation, ab as computeEffectiveWeight, aa as computeSpread, ac as createOrchestrationContext, _ as getCardOrigin, P as getRegisteredNavigator, X as getRegisteredNavigatorNames, V as getRegisteredNavigatorRole, r as getStudySource, Q as hasRegisteredNavigator, Y as initializeNavigatorRegistry, a3 as isFilter, a2 as isGenerator, p as isReview, O as registerNavigator } from '../contentSource-B1p-vdz7.js';
3
- export { D as DataLayerProvider } from '../dataLayerProvider-BWayUIoK.js';
1
+ import { ab as LearnableWeight, M as UserOutcomeRecord, ac as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface, R as ReplanHints, a1 as StrategyContribution } from '../contentSource-CudEz5Tm.js';
2
+ export { K as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, a8 as CardGenerator, aa as CardGeneratorFactory, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, H as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, L as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, a9 as GeneratorContext, G as GeneratorResult, P as HYDRATION_MARKER_ID, Q as HydrationMarker, V as NavigatorConstructor, a4 as NavigatorRole, a5 as NavigatorRoles, a3 as Navigators, j as ScheduledCard, I as SessionTrackingData, i as StudentClassroomDBInterface, h as StudyContentSource, k as StudySessionFailedItem, l as StudySessionFailedNewItem, m as StudySessionFailedReviewItem, S as StudySessionItem, n as StudySessionNewItem, o as StudySessionReviewItem, T as TeacherClassroomDBInterface, J as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, N as UserHydrationState, O as UserHydrationStatus, B as UsrCrsDataInterface, ad as computeDeviation, af as computeEffectiveWeight, ae as computeSpread, ag as createOrchestrationContext, a2 as getCardOrigin, Y as getRegisteredNavigator, $ as getRegisteredNavigatorNames, _ as getRegisteredNavigatorRole, r as getStudySource, Z as hasRegisteredNavigator, a0 as initializeNavigatorRegistry, a7 as isFilter, a6 as isGenerator, p as isReview, X as registerNavigator } from '../contentSource-CudEz5Tm.js';
3
+ export { D as DataLayerProvider } from '../dataLayerProvider-C9WgkBzR.js';
4
4
  import { D as DocType, d as QuestionRecord, b as DocTypePrefixes, C as CardHistory, c as CardRecord } from '../types-legacy-4tlwHnXo.js';
5
5
  export { e as CardData, f as CourseListData, h as DataShapeData, g as DisplayableData, F as Field, G as GuestUsername, Q as QualifiedCardID, i as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-4tlwHnXo.js';
6
6
  import { DataShape, ParsedCard } from '@vue-skuilder/common';
@@ -37,6 +37,53 @@ declare function getSrsBacklogDebug(): SrsBacklogDebug[];
37
37
  /** Drop all captured snapshots (called on session start, alongside pipeline history). */
38
38
  declare function clearSrsBacklogDebug(): void;
39
39
 
40
+ /**
41
+ * A single named pressure reading. The common shape across strategies: a
42
+ * multiplier that climbs under some accumulated condition (staleness, debt,
43
+ * blockage), optionally clamped at a cap.
44
+ */
45
+ interface PressureGaugeDebug {
46
+ /** Stable identifier within the source (e.g. 'group:intro-core:target'). */
47
+ id: string;
48
+ /** Short display label (e.g. 'intro-core targets'). */
49
+ label: string;
50
+ /** Current pressure multiplier (×1.0 = no pressure). */
51
+ multiplier: number;
52
+ /** Clamp ceiling, if the multiplier is capped. Omit for unbounded. */
53
+ max?: number;
54
+ /** One-line context for the reading (counts, mode, staleness). */
55
+ detail?: string;
56
+ /** Expandable rows (blocked target ids, per-tag debt ages, ...). */
57
+ items?: Array<{
58
+ label: string;
59
+ value?: string;
60
+ }>;
61
+ }
62
+ /** One strategy's pressure snapshot for one course, captured once per run. */
63
+ interface StrategyPressureDebug {
64
+ /** Producer identity — implementingClass name (e.g. 'prescribed'). */
65
+ source: string;
66
+ courseId: string;
67
+ gauges: PressureGaugeDebug[];
68
+ /**
69
+ * Highest score this strategy emitted into the candidate pool this run;
70
+ * null if it emitted nothing. Compare against the supplyQ head score to
71
+ * read how the pressure is competing for slots (same crossover read as the
72
+ * SRS panel's `top review`).
73
+ */
74
+ topScore?: number | null;
75
+ /** Label of any one-shot hints emitted alongside the cards this run. */
76
+ hintsLabel?: string;
77
+ /** Epoch ms of capture. */
78
+ timestamp: number;
79
+ }
80
+ /** Called by a strategy once per run. Latest snapshot per (source, course) wins. */
81
+ declare function captureStrategyPressure(snapshot: StrategyPressureDebug): void;
82
+ /** Current pressure snapshot for every source seen, newest-first. */
83
+ declare function getStrategyPressureDebug(): StrategyPressureDebug[];
84
+ /** Drop all captured snapshots (called on session start, alongside pipeline history). */
85
+ declare function clearStrategyPressureDebug(): void;
86
+
40
87
  /**
41
88
  * Snapshot of the learning state for a strategy.
42
89
  *
@@ -805,4 +852,4 @@ declare const userDBDebugAPI: {
805
852
  */
806
853
  declare function mountUserDBDebugger(): void;
807
854
 
808
- export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, CardHistory, CardRecord, CourseDBInterface, DIVERSITY_FLOOR, DIVERSITY_STRENGTH, type DiversityRerankOptions, DocType, DocTypePrefixes, type FilterContext, type FilterImpact, type GeneratorSummary, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, type PipelineForecaster, type PipelineRunReport, QuestionRecord, ReplanHints, type SignalConfig, type SrsBacklogDebug, StrategyContribution, type StrategyLearningState, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, clearSrsBacklogDebug, computeOutcomeSignal, computeStrategyGradient, diversityRerank, docIsDeleted, getActivePipeline, getCardHistoryID, getDefaultLearnableWeight, getSrsBacklogDebug, importParsedCards, isQuestionRecord, mountPipelineDebugger, mountUserDBDebugger, parseCardHistoryID, pipelineDebugAPI, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, userDBDebugAPI, validateProcessorConfig };
855
+ export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, CardHistory, CardRecord, CourseDBInterface, DIVERSITY_FLOOR, DIVERSITY_STRENGTH, type DiversityRerankOptions, DocType, DocTypePrefixes, type FilterContext, type FilterImpact, type GeneratorSummary, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, type PipelineForecaster, type PipelineRunReport, type PressureGaugeDebug, QuestionRecord, ReplanHints, type SignalConfig, type SrsBacklogDebug, StrategyContribution, type StrategyLearningState, type StrategyPressureDebug, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, captureStrategyPressure, clearSrsBacklogDebug, clearStrategyPressureDebug, computeOutcomeSignal, computeStrategyGradient, diversityRerank, docIsDeleted, getActivePipeline, getCardHistoryID, getDefaultLearnableWeight, getSrsBacklogDebug, getStrategyPressureDebug, importParsedCards, isQuestionRecord, mountPipelineDebugger, mountUserDBDebugger, parseCardHistoryID, pipelineDebugAPI, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, userDBDebugAPI, validateProcessorConfig };