@vue-skuilder/db 0.2.7 → 0.2.8

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
@@ -944,6 +944,7 @@ __export(PipelineDebugger_exports, {
944
944
  buildRunReport: () => buildRunReport,
945
945
  captureRun: () => captureRun,
946
946
  clearRunHistory: () => clearRunHistory,
947
+ getActivePipeline: () => getActivePipeline,
947
948
  mountPipelineDebugger: () => mountPipelineDebugger,
948
949
  pipelineDebugAPI: () => pipelineDebugAPI,
949
950
  registerPipelineForDebug: () => registerPipelineForDebug
@@ -951,6 +952,9 @@ __export(PipelineDebugger_exports, {
951
952
  function registerPipelineForDebug(pipeline) {
952
953
  _activePipeline = pipeline;
953
954
  }
955
+ function getActivePipeline() {
956
+ return _activePipeline;
957
+ }
954
958
  function clearRunHistory() {
955
959
  runHistory.length = 0;
956
960
  }
@@ -4983,6 +4987,68 @@ var init_Pipeline = __esm({
4983
4987
  // ---------------------------------------------------------------------------
4984
4988
  // Card-space diagnostic
4985
4989
  // ---------------------------------------------------------------------------
4990
+ /**
4991
+ * Commit-free forecast: score the user's full card space through the filter
4992
+ * chain and return the cards that are currently *reachable* (score >=
4993
+ * threshold), optionally nudged by caller-supplied hints and/or restricted
4994
+ * to cards the user hasn't seen yet.
4995
+ *
4996
+ * This is a GENERIC primitive — it returns scored, tag-hydrated cards and
4997
+ * stops there. It has no knowledge of any particular tag convention; callers
4998
+ * decide what the surviving cards mean (e.g. filter to their own "intro"
4999
+ * tag family). Nothing is written and no session is started.
5000
+ *
5001
+ * The optional `hints` are the "out-of-band kick": they run through the same
5002
+ * {@link applyHints} path a live replan uses, so the two semantics carry over —
5003
+ * - `boostTags`/`boostCards` reweight *within* gating (a gated score-0 card
5004
+ * stays out), and
5005
+ * - `requireTags`/`requireCards` inject from the full pre-filter pool,
5006
+ * *bypassing* gating (use when you want a card regardless of reachability).
5007
+ * Note `unseenOnly` is applied LAST, so it can drop a `require`d card that the
5008
+ * user has already seen — pass `unseenOnly: false` if that matters.
5009
+ *
5010
+ * Cost note: like {@link diagnoseCardSpace}, this scans every card through the
5011
+ * filters, so it's heavier than a normal replan. Intended for one-shot
5012
+ * out-of-band use (e.g. a session-end "what's next" snapshot), not the hot path.
5013
+ *
5014
+ * @param opts.hints Optional ephemeral hints to apply after the filter chain.
5015
+ * @param opts.unseenOnly Only return cards the user hasn't encountered (default true).
5016
+ * @param opts.threshold Min score to count as reachable (default 0.10).
5017
+ * @param opts.limit Optional cap on results (already sorted desc).
5018
+ */
5019
+ async forecast(opts) {
5020
+ const threshold = opts?.threshold ?? 0.1;
5021
+ const unseenOnly = opts?.unseenOnly ?? true;
5022
+ const courseId = this.course.getCourseID();
5023
+ const allCardIds = await this.course.getAllCardIds();
5024
+ let cards = allCardIds.map((cardId) => ({
5025
+ cardId,
5026
+ courseId,
5027
+ score: 1,
5028
+ provenance: []
5029
+ }));
5030
+ cards = await this.hydrateTags(cards);
5031
+ const fullPool = cards.slice();
5032
+ const context = await this.buildContext();
5033
+ for (const filter of this.filters) {
5034
+ cards = await filter.transform(cards, context);
5035
+ }
5036
+ if (opts?.hints) {
5037
+ cards = this.applyHints(cards, opts.hints, fullPool);
5038
+ }
5039
+ cards = cards.filter((c) => c.score >= threshold);
5040
+ if (unseenOnly) {
5041
+ let encountered;
5042
+ try {
5043
+ encountered = new Set(await this.user.getSeenCards(courseId));
5044
+ } catch {
5045
+ encountered = /* @__PURE__ */ new Set();
5046
+ }
5047
+ cards = cards.filter((c) => !encountered.has(c.cardId));
5048
+ }
5049
+ cards.sort((a, b) => b.score - a.score);
5050
+ return opts?.limit ? cards.slice(0, opts.limit) : cards;
5051
+ }
4986
5052
  /**
4987
5053
  * Scan every card in the course through the filter chain and report
4988
5054
  * how many are "well indicated" (score >= threshold) for the current user.
@@ -5280,6 +5346,7 @@ __export(navigators_exports, {
5280
5346
  NavigatorRoles: () => NavigatorRoles,
5281
5347
  Navigators: () => Navigators,
5282
5348
  diversityRerank: () => diversityRerank,
5349
+ getActivePipeline: () => getActivePipeline,
5283
5350
  getCardOrigin: () => getCardOrigin,
5284
5351
  getRegisteredNavigator: () => getRegisteredNavigator,
5285
5352
  getRegisteredNavigatorNames: () => getRegisteredNavigatorNames,
@@ -14970,6 +15037,7 @@ export {
14970
15037
  docIsDeleted,
14971
15038
  endSessionTracking,
14972
15039
  ensureAppDataDirectory,
15040
+ getActivePipeline,
14973
15041
  getAppDataDirectory,
14974
15042
  getCardHistoryID,
14975
15043
  getCardOrigin,