@vue-skuilder/db 0.1.24 → 0.1.25

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 (50) hide show
  1. package/dist/{contentSource-BotbOOfX.d.ts → contentSource-BmnmvH8C.d.ts} +41 -0
  2. package/dist/{contentSource-C90LH-OH.d.cts → contentSource-DfBbaLA-.d.cts} +41 -0
  3. package/dist/core/index.d.cts +94 -4
  4. package/dist/core/index.d.ts +94 -4
  5. package/dist/core/index.js +530 -83
  6. package/dist/core/index.js.map +1 -1
  7. package/dist/core/index.mjs +528 -83
  8. package/dist/core/index.mjs.map +1 -1
  9. package/dist/{dataLayerProvider-DGKp4zFB.d.cts → dataLayerProvider-BeRXVMs5.d.cts} +1 -1
  10. package/dist/{dataLayerProvider-SBpz9jQf.d.ts → dataLayerProvider-CG9GfaAY.d.ts} +1 -1
  11. package/dist/impl/couch/index.d.cts +2 -2
  12. package/dist/impl/couch/index.d.ts +2 -2
  13. package/dist/impl/couch/index.js +526 -83
  14. package/dist/impl/couch/index.js.map +1 -1
  15. package/dist/impl/couch/index.mjs +526 -83
  16. package/dist/impl/couch/index.mjs.map +1 -1
  17. package/dist/impl/static/index.d.cts +2 -2
  18. package/dist/impl/static/index.d.ts +2 -2
  19. package/dist/impl/static/index.js +526 -83
  20. package/dist/impl/static/index.js.map +1 -1
  21. package/dist/impl/static/index.mjs +526 -83
  22. package/dist/impl/static/index.mjs.map +1 -1
  23. package/dist/index.d.cts +247 -14
  24. package/dist/index.d.ts +247 -14
  25. package/dist/index.js +1419 -140
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +1409 -137
  28. package/dist/index.mjs.map +1 -1
  29. package/docs/navigators-architecture.md +22 -4
  30. package/docs/todo-review-urgency-adaptation.md +205 -0
  31. package/package.json +3 -3
  32. package/src/core/interfaces/userDB.ts +44 -0
  33. package/src/core/navigators/Pipeline.ts +86 -5
  34. package/src/core/navigators/PipelineAssembler.ts +7 -21
  35. package/src/core/navigators/PipelineDebugger.ts +426 -0
  36. package/src/core/navigators/generators/CompositeGenerator.ts +21 -0
  37. package/src/core/navigators/generators/elo.ts +14 -1
  38. package/src/core/navigators/generators/srs.ts +146 -18
  39. package/src/core/navigators/index.ts +9 -0
  40. package/src/impl/couch/user-course-relDB.ts +12 -0
  41. package/src/study/MixerDebugger.ts +555 -0
  42. package/src/study/SessionController.ts +95 -19
  43. package/src/study/SessionDebugger.ts +442 -0
  44. package/src/study/SourceMixer.ts +36 -17
  45. package/src/study/TODO-session-scheduling.md +133 -0
  46. package/src/study/index.ts +2 -0
  47. package/src/study/services/EloService.ts +79 -4
  48. package/src/study/services/ResponseProcessor.ts +130 -72
  49. package/src/study/services/SrsService.ts +9 -0
  50. package/tests/core/navigators/PipelineAssembler.test.ts +4 -4
@@ -469,6 +469,11 @@ interface UserDBReader {
469
469
  * Strategies use this to persist preferences, learned patterns, or temporal
470
470
  * tracking data across sessions. Each strategy owns its own namespace.
471
471
  *
472
+ * @deprecated Use `getCourseInterface(courseId).getStrategyState(strategyKey)` instead.
473
+ * Direct use bypasses course-scoping safety — the courseId parameter is unguarded,
474
+ * allowing accidental cross-course data access. The course-scoped interface binds
475
+ * courseId once at construction.
476
+ *
472
477
  * @param courseId - The course this state applies to
473
478
  * @param strategyKey - Unique key identifying the strategy (typically class name)
474
479
  * @returns The strategy's data payload, or null if no state exists
@@ -544,6 +549,11 @@ interface UserDBWriter extends DocumentUpdater {
544
549
  * Strategies use this to persist preferences, learned patterns, or temporal
545
550
  * tracking data across sessions. Each strategy owns its own namespace.
546
551
  *
552
+ * @deprecated Use `getCourseInterface(courseId).putStrategyState(strategyKey, data)` instead.
553
+ * Direct use bypasses course-scoping safety — the courseId parameter is unguarded,
554
+ * allowing accidental cross-course data writes. The course-scoped interface binds
555
+ * courseId once at construction.
556
+ *
547
557
  * @param courseId - The course this state applies to
548
558
  * @param strategyKey - Unique key identifying the strategy (typically class name)
549
559
  * @param data - The strategy's data payload to store
@@ -552,6 +562,9 @@ interface UserDBWriter extends DocumentUpdater {
552
562
  /**
553
563
  * Delete strategy-specific state for a course.
554
564
  *
565
+ * @deprecated Use `getCourseInterface(courseId).deleteStrategyState(strategyKey)` instead.
566
+ * Direct use bypasses course-scoping safety.
567
+ *
555
568
  * @param courseId - The course this state applies to
556
569
  * @param strategyKey - Unique key identifying the strategy (typically class name)
557
570
  */
@@ -604,6 +617,34 @@ interface UsrCrsDataInterface {
604
617
  getScheduledReviewCount(): Promise<number>;
605
618
  getCourseSettings(): Promise<UserCourseSettings>;
606
619
  updateCourseSettings(updates: UserCourseSetting[]): void;
620
+ /**
621
+ * Get strategy-specific state for this course.
622
+ *
623
+ * Course-scoped alternative to `UserDBInterface.getStrategyState()`.
624
+ * The courseId is bound at construction via `getCourseInterface(courseId)`,
625
+ * so callers cannot accidentally access another course's state.
626
+ *
627
+ * @param strategyKey - Unique key identifying the state document
628
+ * @returns The state payload, or null if no state exists
629
+ */
630
+ getStrategyState<T>(strategyKey: string): Promise<T | null>;
631
+ /**
632
+ * Store strategy-specific state for this course.
633
+ *
634
+ * Course-scoped alternative to `UserDBInterface.putStrategyState()`.
635
+ *
636
+ * @param strategyKey - Unique key identifying the state document
637
+ * @param data - The state payload to store
638
+ */
639
+ putStrategyState<T>(strategyKey: string, data: T): Promise<void>;
640
+ /**
641
+ * Delete strategy-specific state for this course.
642
+ *
643
+ * Course-scoped alternative to `UserDBInterface.deleteStrategyState()`.
644
+ *
645
+ * @param strategyKey - Unique key identifying the state document
646
+ */
647
+ deleteStrategyState(strategyKey: string): Promise<void>;
607
648
  }
608
649
  type ClassroomRegistrationDesignation = 'student' | 'teacher' | 'aide' | 'admin';
609
650
  interface ClassroomRegistration {
@@ -469,6 +469,11 @@ interface UserDBReader {
469
469
  * Strategies use this to persist preferences, learned patterns, or temporal
470
470
  * tracking data across sessions. Each strategy owns its own namespace.
471
471
  *
472
+ * @deprecated Use `getCourseInterface(courseId).getStrategyState(strategyKey)` instead.
473
+ * Direct use bypasses course-scoping safety — the courseId parameter is unguarded,
474
+ * allowing accidental cross-course data access. The course-scoped interface binds
475
+ * courseId once at construction.
476
+ *
472
477
  * @param courseId - The course this state applies to
473
478
  * @param strategyKey - Unique key identifying the strategy (typically class name)
474
479
  * @returns The strategy's data payload, or null if no state exists
@@ -544,6 +549,11 @@ interface UserDBWriter extends DocumentUpdater {
544
549
  * Strategies use this to persist preferences, learned patterns, or temporal
545
550
  * tracking data across sessions. Each strategy owns its own namespace.
546
551
  *
552
+ * @deprecated Use `getCourseInterface(courseId).putStrategyState(strategyKey, data)` instead.
553
+ * Direct use bypasses course-scoping safety — the courseId parameter is unguarded,
554
+ * allowing accidental cross-course data writes. The course-scoped interface binds
555
+ * courseId once at construction.
556
+ *
547
557
  * @param courseId - The course this state applies to
548
558
  * @param strategyKey - Unique key identifying the strategy (typically class name)
549
559
  * @param data - The strategy's data payload to store
@@ -552,6 +562,9 @@ interface UserDBWriter extends DocumentUpdater {
552
562
  /**
553
563
  * Delete strategy-specific state for a course.
554
564
  *
565
+ * @deprecated Use `getCourseInterface(courseId).deleteStrategyState(strategyKey)` instead.
566
+ * Direct use bypasses course-scoping safety.
567
+ *
555
568
  * @param courseId - The course this state applies to
556
569
  * @param strategyKey - Unique key identifying the strategy (typically class name)
557
570
  */
@@ -604,6 +617,34 @@ interface UsrCrsDataInterface {
604
617
  getScheduledReviewCount(): Promise<number>;
605
618
  getCourseSettings(): Promise<UserCourseSettings>;
606
619
  updateCourseSettings(updates: UserCourseSetting[]): void;
620
+ /**
621
+ * Get strategy-specific state for this course.
622
+ *
623
+ * Course-scoped alternative to `UserDBInterface.getStrategyState()`.
624
+ * The courseId is bound at construction via `getCourseInterface(courseId)`,
625
+ * so callers cannot accidentally access another course's state.
626
+ *
627
+ * @param strategyKey - Unique key identifying the state document
628
+ * @returns The state payload, or null if no state exists
629
+ */
630
+ getStrategyState<T>(strategyKey: string): Promise<T | null>;
631
+ /**
632
+ * Store strategy-specific state for this course.
633
+ *
634
+ * Course-scoped alternative to `UserDBInterface.putStrategyState()`.
635
+ *
636
+ * @param strategyKey - Unique key identifying the state document
637
+ * @param data - The state payload to store
638
+ */
639
+ putStrategyState<T>(strategyKey: string, data: T): Promise<void>;
640
+ /**
641
+ * Delete strategy-specific state for this course.
642
+ *
643
+ * Course-scoped alternative to `UserDBInterface.deleteStrategyState()`.
644
+ *
645
+ * @param strategyKey - Unique key identifying the state document
646
+ */
647
+ deleteStrategyState(strategyKey: string): Promise<void>;
607
648
  }
608
649
  type ClassroomRegistrationDesignation = 'student' | 'teacher' | 'aide' | 'admin';
609
650
  interface ClassroomRegistration {
@@ -1,6 +1,6 @@
1
- import { a1 as LearnableWeight, L as UserOutcomeRecord, a2 as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface } from '../contentSource-C90LH-OH.cjs';
2
- export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, K as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, N as NavigatorConstructor, Z as NavigatorRole, _ as NavigatorRoles, Y as Navigators, j as ScheduledCard, H as SessionTrackingData, V as StrategyContribution, 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, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, a3 as computeDeviation, a5 as computeEffectiveWeight, a4 as computeSpread, a6 as createOrchestrationContext, X as getCardOrigin, O as getRegisteredNavigator, Q as getRegisteredNavigatorNames, r as getStudySource, P as hasRegisteredNavigator, R as initializeNavigatorRegistry, a0 as isFilter, $ as isGenerator, p as isReview, M as registerNavigator } from '../contentSource-C90LH-OH.cjs';
3
- export { D as DataLayerProvider } from '../dataLayerProvider-DGKp4zFB.cjs';
1
+ import { a1 as LearnableWeight, L as UserOutcomeRecord, a2 as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface, V as StrategyContribution } from '../contentSource-DfBbaLA-.cjs';
2
+ export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, K as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, N as NavigatorConstructor, Z as NavigatorRole, _ as NavigatorRoles, Y as Navigators, j as ScheduledCard, H 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, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, a3 as computeDeviation, a5 as computeEffectiveWeight, a4 as computeSpread, a6 as createOrchestrationContext, X as getCardOrigin, O as getRegisteredNavigator, Q as getRegisteredNavigatorNames, r as getStudySource, P as hasRegisteredNavigator, R as initializeNavigatorRegistry, a0 as isFilter, $ as isGenerator, p as isReview, M as registerNavigator } from '../contentSource-DfBbaLA-.cjs';
3
+ export { D as DataLayerProvider } from '../dataLayerProvider-BeRXVMs5.cjs';
4
4
  import { D as DocType, i as QuestionRecord, b as DocTypePrefixes, C as CardHistory, c as CardRecord } from '../types-legacy-JXDxinpU.cjs';
5
5
  export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-JXDxinpU.cjs';
6
6
  import { DataShape, ParsedCard } from '@vue-skuilder/common';
@@ -383,6 +383,96 @@ interface CardGenerator {
383
383
  */
384
384
  type CardGeneratorFactory<TConfig = unknown> = (config: TConfig) => CardGenerator;
385
385
 
386
+ /**
387
+ * Summary of a single generator's contribution.
388
+ */
389
+ interface GeneratorSummary {
390
+ name: string;
391
+ cardCount: number;
392
+ newCount: number;
393
+ reviewCount: number;
394
+ topScore: number;
395
+ }
396
+ /**
397
+ * Summary of a filter's impact on scores.
398
+ */
399
+ interface FilterImpact {
400
+ name: string;
401
+ boosted: number;
402
+ penalized: number;
403
+ passed: number;
404
+ removed: number;
405
+ }
406
+ /**
407
+ * Complete record of a single pipeline execution.
408
+ */
409
+ interface PipelineRunReport {
410
+ runId: string;
411
+ timestamp: Date;
412
+ courseId: string;
413
+ courseName?: string;
414
+ generatorName: string;
415
+ generators?: GeneratorSummary[];
416
+ generatedCount: number;
417
+ filters: FilterImpact[];
418
+ finalCount: number;
419
+ reviewsSelected: number;
420
+ newSelected: number;
421
+ cards: Array<{
422
+ cardId: string;
423
+ courseId: string;
424
+ origin: 'new' | 'review' | 'unknown';
425
+ finalScore: number;
426
+ provenance: StrategyContribution[];
427
+ selected: boolean;
428
+ }>;
429
+ }
430
+ /**
431
+ * Console API object exposed on window.skuilder.pipeline
432
+ */
433
+ declare const pipelineDebugAPI: {
434
+ /**
435
+ * Get raw run history for programmatic access.
436
+ */
437
+ readonly runs: PipelineRunReport[];
438
+ /**
439
+ * Show summary of a specific pipeline run.
440
+ */
441
+ showRun(idOrIndex?: string | number): void;
442
+ /**
443
+ * Show summary of the last pipeline run.
444
+ */
445
+ showLastRun(): void;
446
+ /**
447
+ * Show detailed provenance for a specific card.
448
+ */
449
+ showCard(cardId: string): void;
450
+ /**
451
+ * Explain why reviews may or may not have been selected.
452
+ */
453
+ explainReviews(): void;
454
+ /**
455
+ * Show all runs in compact format.
456
+ */
457
+ listRuns(): void;
458
+ /**
459
+ * Export run history as JSON for bug reports.
460
+ */
461
+ export(): string;
462
+ /**
463
+ * Clear run history.
464
+ */
465
+ clear(): void;
466
+ /**
467
+ * Show help.
468
+ */
469
+ help(): void;
470
+ };
471
+ /**
472
+ * Mount the debug API on window.skuilder.pipeline
473
+ */
474
+ declare function mountPipelineDebugger(): void;
475
+
386
476
  /**
387
477
  * Template literal type for strategy state document IDs.
388
478
  *
@@ -515,4 +605,4 @@ declare function validateProcessorConfig(config: Partial<BulkCardProcessorConfig
515
605
  errorMessage?: string;
516
606
  };
517
607
 
518
- export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, type CardGenerator, type CardGeneratorFactory, CardHistory, CardRecord, CourseDBInterface, DocType, DocTypePrefixes, type FilterContext, type GeneratorContext, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, QuestionRecord, type SignalConfig, type StrategyLearningState, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, computeOutcomeSignal, computeStrategyGradient, docIsDeleted, getCardHistoryID, getDefaultLearnableWeight, importParsedCards, isQuestionRecord, parseCardHistoryID, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, validateProcessorConfig };
608
+ export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, type CardGenerator, type CardGeneratorFactory, CardHistory, CardRecord, CourseDBInterface, DocType, DocTypePrefixes, type FilterContext, type FilterImpact, type GeneratorContext, type GeneratorSummary, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, type PipelineRunReport, QuestionRecord, type SignalConfig, StrategyContribution, type StrategyLearningState, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, computeOutcomeSignal, computeStrategyGradient, docIsDeleted, getCardHistoryID, getDefaultLearnableWeight, importParsedCards, isQuestionRecord, mountPipelineDebugger, parseCardHistoryID, pipelineDebugAPI, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, validateProcessorConfig };
@@ -1,6 +1,6 @@
1
- import { a1 as LearnableWeight, L as UserOutcomeRecord, a2 as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface } from '../contentSource-BotbOOfX.js';
2
- export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, K as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, N as NavigatorConstructor, Z as NavigatorRole, _ as NavigatorRoles, Y as Navigators, j as ScheduledCard, H as SessionTrackingData, V as StrategyContribution, 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, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, a3 as computeDeviation, a5 as computeEffectiveWeight, a4 as computeSpread, a6 as createOrchestrationContext, X as getCardOrigin, O as getRegisteredNavigator, Q as getRegisteredNavigatorNames, r as getStudySource, P as hasRegisteredNavigator, R as initializeNavigatorRegistry, a0 as isFilter, $ as isGenerator, p as isReview, M as registerNavigator } from '../contentSource-BotbOOfX.js';
3
- export { D as DataLayerProvider } from '../dataLayerProvider-SBpz9jQf.js';
1
+ import { a1 as LearnableWeight, L as UserOutcomeRecord, a2 as OrchestrationContext, W as WeightedCard, U as UserDBInterface, C as CourseDBInterface, V as StrategyContribution } from '../contentSource-BmnmvH8C.js';
2
+ export { J as ActivityRecord, A as AdminDBInterface, v as AssignedCard, g as AssignedContent, u as AssignedCourse, t as AssignedTag, c as ClassroomDBInterface, F as ClassroomRegistration, E as ClassroomRegistrationDesignation, G as ClassroomRegistrationDoc, e as ContentNavigationStrategyData, f as ContentNavigator, q as ContentSourceID, d as CourseInfo, K as CourseRegistration, s as CourseRegistrationDoc, b as CoursesDBInterface, N as NavigatorConstructor, Z as NavigatorRole, _ as NavigatorRoles, Y as Navigators, j as ScheduledCard, H 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, I as UserConfig, z as UserCourseSetting, y as UserCourseSettings, x as UserDBAuthenticator, a as UserDBReader, w as UserDBWriter, B as UsrCrsDataInterface, a3 as computeDeviation, a5 as computeEffectiveWeight, a4 as computeSpread, a6 as createOrchestrationContext, X as getCardOrigin, O as getRegisteredNavigator, Q as getRegisteredNavigatorNames, r as getStudySource, P as hasRegisteredNavigator, R as initializeNavigatorRegistry, a0 as isFilter, $ as isGenerator, p as isReview, M as registerNavigator } from '../contentSource-BmnmvH8C.js';
3
+ export { D as DataLayerProvider } from '../dataLayerProvider-CG9GfaAY.js';
4
4
  import { D as DocType, i as QuestionRecord, b as DocTypePrefixes, C as CardHistory, c as CardRecord } from '../types-legacy-JXDxinpU.js';
5
5
  export { d as CardData, e as CourseListData, g as DataShapeData, f as DisplayableData, F as Field, G as GuestUsername, Q as QualifiedCardID, h as QuestionData, S as SkuilderCourseData, a as Tag, T as TagStub, l as log } from '../types-legacy-JXDxinpU.js';
6
6
  import { DataShape, ParsedCard } from '@vue-skuilder/common';
@@ -383,6 +383,96 @@ interface CardGenerator {
383
383
  */
384
384
  type CardGeneratorFactory<TConfig = unknown> = (config: TConfig) => CardGenerator;
385
385
 
386
+ /**
387
+ * Summary of a single generator's contribution.
388
+ */
389
+ interface GeneratorSummary {
390
+ name: string;
391
+ cardCount: number;
392
+ newCount: number;
393
+ reviewCount: number;
394
+ topScore: number;
395
+ }
396
+ /**
397
+ * Summary of a filter's impact on scores.
398
+ */
399
+ interface FilterImpact {
400
+ name: string;
401
+ boosted: number;
402
+ penalized: number;
403
+ passed: number;
404
+ removed: number;
405
+ }
406
+ /**
407
+ * Complete record of a single pipeline execution.
408
+ */
409
+ interface PipelineRunReport {
410
+ runId: string;
411
+ timestamp: Date;
412
+ courseId: string;
413
+ courseName?: string;
414
+ generatorName: string;
415
+ generators?: GeneratorSummary[];
416
+ generatedCount: number;
417
+ filters: FilterImpact[];
418
+ finalCount: number;
419
+ reviewsSelected: number;
420
+ newSelected: number;
421
+ cards: Array<{
422
+ cardId: string;
423
+ courseId: string;
424
+ origin: 'new' | 'review' | 'unknown';
425
+ finalScore: number;
426
+ provenance: StrategyContribution[];
427
+ selected: boolean;
428
+ }>;
429
+ }
430
+ /**
431
+ * Console API object exposed on window.skuilder.pipeline
432
+ */
433
+ declare const pipelineDebugAPI: {
434
+ /**
435
+ * Get raw run history for programmatic access.
436
+ */
437
+ readonly runs: PipelineRunReport[];
438
+ /**
439
+ * Show summary of a specific pipeline run.
440
+ */
441
+ showRun(idOrIndex?: string | number): void;
442
+ /**
443
+ * Show summary of the last pipeline run.
444
+ */
445
+ showLastRun(): void;
446
+ /**
447
+ * Show detailed provenance for a specific card.
448
+ */
449
+ showCard(cardId: string): void;
450
+ /**
451
+ * Explain why reviews may or may not have been selected.
452
+ */
453
+ explainReviews(): void;
454
+ /**
455
+ * Show all runs in compact format.
456
+ */
457
+ listRuns(): void;
458
+ /**
459
+ * Export run history as JSON for bug reports.
460
+ */
461
+ export(): string;
462
+ /**
463
+ * Clear run history.
464
+ */
465
+ clear(): void;
466
+ /**
467
+ * Show help.
468
+ */
469
+ help(): void;
470
+ };
471
+ /**
472
+ * Mount the debug API on window.skuilder.pipeline
473
+ */
474
+ declare function mountPipelineDebugger(): void;
475
+
386
476
  /**
387
477
  * Template literal type for strategy state document IDs.
388
478
  *
@@ -515,4 +605,4 @@ declare function validateProcessorConfig(config: Partial<BulkCardProcessorConfig
515
605
  errorMessage?: string;
516
606
  };
517
607
 
518
- export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, type CardGenerator, type CardGeneratorFactory, CardHistory, CardRecord, CourseDBInterface, DocType, DocTypePrefixes, type FilterContext, type GeneratorContext, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, QuestionRecord, type SignalConfig, type StrategyLearningState, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, computeOutcomeSignal, computeStrategyGradient, docIsDeleted, getCardHistoryID, getDefaultLearnableWeight, importParsedCards, isQuestionRecord, parseCardHistoryID, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, validateProcessorConfig };
608
+ export { type BulkCardProcessorConfig, type CardFilter, type CardFilterFactory, type CardGenerator, type CardGeneratorFactory, CardHistory, CardRecord, CourseDBInterface, DocType, DocTypePrefixes, type FilterContext, type FilterImpact, type GeneratorContext, type GeneratorSummary, type GradientObservation, type GradientResult, type ImportResult, LearnableWeight, Loggable, OrchestrationContext, type PeriodUpdateInput, type PeriodUpdateResult, type PipelineRunReport, QuestionRecord, type SignalConfig, StrategyContribution, type StrategyLearningState, type StrategyStateDoc, type StrategyStateId, UserDBInterface, UserOutcomeRecord, WeightedCard, aggregateOutcomesForGradient, areQuestionRecords, buildStrategyStateId, computeOutcomeSignal, computeStrategyGradient, docIsDeleted, getCardHistoryID, getDefaultLearnableWeight, importParsedCards, isQuestionRecord, mountPipelineDebugger, parseCardHistoryID, pipelineDebugAPI, recordUserOutcome, runPeriodUpdate, scoreAccuracyInZone, updateLearningState, updateStrategyWeight, validateProcessorConfig };