@vue-skuilder/db 0.2.8 → 0.2.9
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/{contentSource-Cplhv3bJ.d.ts → contentSource-C-0t0y0V.d.ts} +7 -0
- package/dist/{contentSource-kI9_jwTu.d.cts → contentSource-jSkcOt2s.d.cts} +7 -0
- package/dist/core/index.d.cts +29 -4
- package/dist/core/index.d.ts +29 -4
- package/dist/core/index.js +132 -39
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +130 -39
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-DrBqOUa3.d.ts → dataLayerProvider-BB0oi9T0.d.ts} +1 -1
- package/dist/{dataLayerProvider-CiA2Rr0v.d.cts → dataLayerProvider-BDClIrFC.d.cts} +1 -1
- package/dist/impl/couch/index.d.cts +2 -2
- package/dist/impl/couch/index.d.ts +2 -2
- package/dist/impl/couch/index.js +128 -39
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +128 -39
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.cts +2 -2
- package/dist/impl/static/index.d.ts +2 -2
- package/dist/impl/static/index.js +128 -39
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +128 -39
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/index.d.cts +115 -81
- package/dist/index.d.ts +115 -81
- package/dist/index.js +371 -251
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +369 -251
- package/dist/index.mjs.map +1 -1
- package/docs/navigators-architecture.md +29 -13
- package/package.json +3 -3
- package/src/core/interfaces/contentSource.ts +7 -0
- package/src/core/navigators/SrsDebugger.ts +53 -0
- package/src/core/navigators/generators/prescribed.ts +76 -9
- package/src/core/navigators/generators/srs.ts +81 -37
- package/src/core/navigators/index.ts +5 -0
- package/src/study/SessionController.ts +260 -249
- package/src/study/SessionDebugger.ts +15 -25
- package/src/study/SessionOverlay.ts +108 -13
|
@@ -1542,6 +1542,30 @@ Example:
|
|
|
1542
1542
|
}
|
|
1543
1543
|
});
|
|
1544
1544
|
|
|
1545
|
+
// src/core/navigators/SrsDebugger.ts
|
|
1546
|
+
var SrsDebugger_exports = {};
|
|
1547
|
+
__export(SrsDebugger_exports, {
|
|
1548
|
+
captureSrsBacklog: () => captureSrsBacklog,
|
|
1549
|
+
clearSrsBacklogDebug: () => clearSrsBacklogDebug,
|
|
1550
|
+
getSrsBacklogDebug: () => getSrsBacklogDebug
|
|
1551
|
+
});
|
|
1552
|
+
function captureSrsBacklog(snapshot) {
|
|
1553
|
+
snapshots.set(snapshot.courseId, snapshot);
|
|
1554
|
+
}
|
|
1555
|
+
function getSrsBacklogDebug() {
|
|
1556
|
+
return [...snapshots.values()].sort((a, b) => b.timestamp - a.timestamp);
|
|
1557
|
+
}
|
|
1558
|
+
function clearSrsBacklogDebug() {
|
|
1559
|
+
snapshots.clear();
|
|
1560
|
+
}
|
|
1561
|
+
var snapshots;
|
|
1562
|
+
var init_SrsDebugger = __esm({
|
|
1563
|
+
"src/core/navigators/SrsDebugger.ts"() {
|
|
1564
|
+
"use strict";
|
|
1565
|
+
snapshots = /* @__PURE__ */ new Map();
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
|
|
1545
1569
|
// src/core/navigators/generators/CompositeGenerator.ts
|
|
1546
1570
|
var CompositeGenerator_exports = {};
|
|
1547
1571
|
__export(CompositeGenerator_exports, {
|
|
@@ -1909,7 +1933,7 @@ function shuffleInPlace(arr) {
|
|
|
1909
1933
|
function pickTopByScore(cards, limit) {
|
|
1910
1934
|
return [...cards].sort((a, b) => b.score - a.score || a.cardId.localeCompare(b.cardId)).slice(0, limit);
|
|
1911
1935
|
}
|
|
1912
|
-
var DEFAULT_FRESHNESS_WINDOW, DEFAULT_MAX_DIRECT_PER_RUN, DEFAULT_MAX_SUPPORT_PER_RUN, DEFAULT_HIERARCHY_DEPTH, DEFAULT_MIN_COUNT, DEFAULT_PRACTICE_MIN_COUNT, DEFAULT_MAX_PRACTICE_PER_RUN, BASE_TARGET_SCORE, BASE_SUPPORT_SCORE, DISCOVERED_SUPPORT_SCORE, BASE_PRACTICE_SCORE, MAX_TARGET_MULTIPLIER, MAX_SUPPORT_MULTIPLIER, PRESCRIBED_DEBUG_VERSION, PrescribedCardsGenerator;
|
|
1936
|
+
var DEFAULT_FRESHNESS_WINDOW, DEFAULT_MAX_DIRECT_PER_RUN, DEFAULT_MAX_SUPPORT_PER_RUN, DEFAULT_HIERARCHY_DEPTH, DEFAULT_MIN_COUNT, DEFAULT_PRACTICE_MIN_COUNT, DEFAULT_MAX_PRACTICE_PER_RUN, BASE_TARGET_SCORE, BASE_SUPPORT_SCORE, DISCOVERED_SUPPORT_SCORE, BASE_PRACTICE_SCORE, PRACTICE_BASE_MULT, MAX_PRACTICE_MULTIPLIER, PRACTICE_STALENESS_BUMP_PER_DAY, MAX_TARGET_MULTIPLIER, MAX_SUPPORT_MULTIPLIER, PRESCRIBED_DEBUG_VERSION, PrescribedCardsGenerator;
|
|
1913
1937
|
var init_prescribed = __esm({
|
|
1914
1938
|
"src/core/navigators/generators/prescribed.ts"() {
|
|
1915
1939
|
"use strict";
|
|
@@ -1926,6 +1950,9 @@ var init_prescribed = __esm({
|
|
|
1926
1950
|
BASE_SUPPORT_SCORE = 0.8;
|
|
1927
1951
|
DISCOVERED_SUPPORT_SCORE = 12;
|
|
1928
1952
|
BASE_PRACTICE_SCORE = 1;
|
|
1953
|
+
PRACTICE_BASE_MULT = 2;
|
|
1954
|
+
MAX_PRACTICE_MULTIPLIER = 4;
|
|
1955
|
+
PRACTICE_STALENESS_BUMP_PER_DAY = 0.5;
|
|
1929
1956
|
MAX_TARGET_MULTIPLIER = 8;
|
|
1930
1957
|
MAX_SUPPORT_MULTIPLIER = 4;
|
|
1931
1958
|
PRESCRIBED_DEBUG_VERSION = "testversion-prescribed-v3";
|
|
@@ -1985,6 +2012,8 @@ var init_prescribed = __esm({
|
|
|
1985
2012
|
const emitted = [];
|
|
1986
2013
|
const emittedIds = /* @__PURE__ */ new Set();
|
|
1987
2014
|
const groupRuntimes = [];
|
|
2015
|
+
const priorPracticeDebt = progress.practiceDebt ?? {};
|
|
2016
|
+
const nextPracticeDebt = {};
|
|
1988
2017
|
for (const group of this.config.groups) {
|
|
1989
2018
|
const runtime = this.buildGroupRuntimeState({
|
|
1990
2019
|
group,
|
|
@@ -2042,10 +2071,13 @@ var init_prescribed = __esm({
|
|
|
2042
2071
|
userTagElo,
|
|
2043
2072
|
userGlobalElo,
|
|
2044
2073
|
activeIds,
|
|
2045
|
-
seenIds
|
|
2074
|
+
seenIds,
|
|
2075
|
+
priorPracticeDebt,
|
|
2076
|
+
nextPracticeDebt
|
|
2046
2077
|
});
|
|
2047
2078
|
emitted.push(...directCards, ...supportCards, ...discoveredSupportCards, ...practiceCards);
|
|
2048
2079
|
}
|
|
2080
|
+
nextState.practiceDebt = nextPracticeDebt;
|
|
2049
2081
|
const hintSummary = this.buildSupportHintSummary(groupRuntimes);
|
|
2050
2082
|
const hints = Object.keys(hintSummary.boostTags).length > 0 ? {
|
|
2051
2083
|
boostTags: hintSummary.boostTags,
|
|
@@ -2379,9 +2411,16 @@ var init_prescribed = __esm({
|
|
|
2379
2411
|
* `practiceMinCount`), this resolves cards carrying that tag and emits them
|
|
2380
2412
|
* into the candidate pool. It exists because global-ELO retrieval
|
|
2381
2413
|
* systematically fails to fetch the (low-ELO) drill cards for a
|
|
2382
|
-
* freshly-introduced skill — putting them in the pool here
|
|
2383
|
-
*
|
|
2384
|
-
*
|
|
2414
|
+
* freshly-introduced skill — putting them in the pool here guarantees presence.
|
|
2415
|
+
*
|
|
2416
|
+
* Emphasis is a **practice-debt pressure** (parallel to SRS backlog pressure):
|
|
2417
|
+
* cards score `base × multiplier`, where the multiplier starts at
|
|
2418
|
+
* PRACTICE_BASE_MULT (so a few reps land promptly post-intro, competing with
|
|
2419
|
+
* pressured reviews) and escalates by how long the debt has stayed open
|
|
2420
|
+
* (per-tag, time-based via `priorPracticeDebt`/`nextPracticeDebt`), clamped at
|
|
2421
|
+
* MAX_PRACTICE_MULTIPLIER. The debt is durable and self-discharges the instant
|
|
2422
|
+
* the skill reaches `practiceMinCount` — so this no longer relies on the
|
|
2423
|
+
* session-scoped intro boost to actually surface.
|
|
2385
2424
|
*
|
|
2386
2425
|
* Fully data-driven: the unlock relation comes from the hierarchy config and
|
|
2387
2426
|
* practice-status from per-tag ELO. No card-id or tag-namespace hard-coding.
|
|
@@ -2396,7 +2435,9 @@ var init_prescribed = __esm({
|
|
|
2396
2435
|
userTagElo,
|
|
2397
2436
|
userGlobalElo,
|
|
2398
2437
|
activeIds,
|
|
2399
|
-
seenIds
|
|
2438
|
+
seenIds,
|
|
2439
|
+
priorPracticeDebt,
|
|
2440
|
+
nextPracticeDebt
|
|
2400
2441
|
} = args;
|
|
2401
2442
|
const patterns = group.practiceTagPatterns ?? [];
|
|
2402
2443
|
if (patterns.length === 0) return [];
|
|
@@ -2406,6 +2447,20 @@ var init_prescribed = __esm({
|
|
|
2406
2447
|
(tag) => patterns.some((p) => matchesTagPattern(tag, p)) && this.isUnlockedGatedSkill(tag, hierarchyConfigs, userTagElo, userGlobalElo) && (userTagElo[tag]?.count ?? 0) < practiceMinCount
|
|
2407
2448
|
);
|
|
2408
2449
|
if (practiceTags.length === 0) return [];
|
|
2450
|
+
const now = Date.now();
|
|
2451
|
+
const DAY_MS = 24 * 60 * 60 * 1e3;
|
|
2452
|
+
const tagMultiplier = /* @__PURE__ */ new Map();
|
|
2453
|
+
for (const tag of practiceTags) {
|
|
2454
|
+
const firstOwedAt = priorPracticeDebt[tag] ?? isoNow();
|
|
2455
|
+
nextPracticeDebt[tag] = firstOwedAt;
|
|
2456
|
+
const staleDays = Math.max(0, (now - new Date(firstOwedAt).getTime()) / DAY_MS);
|
|
2457
|
+
const mult = clamp(
|
|
2458
|
+
PRACTICE_BASE_MULT + staleDays * PRACTICE_STALENESS_BUMP_PER_DAY,
|
|
2459
|
+
PRACTICE_BASE_MULT,
|
|
2460
|
+
MAX_PRACTICE_MULTIPLIER
|
|
2461
|
+
);
|
|
2462
|
+
tagMultiplier.set(tag, mult);
|
|
2463
|
+
}
|
|
2409
2464
|
const practiceCardIds = this.findDiscoveredSupportCards({
|
|
2410
2465
|
supportTags: practiceTags,
|
|
2411
2466
|
cardsByTag,
|
|
@@ -2421,18 +2476,25 @@ var init_prescribed = __esm({
|
|
|
2421
2476
|
const cards = [];
|
|
2422
2477
|
for (const cardId of practiceCardIds) {
|
|
2423
2478
|
emittedIds.add(cardId);
|
|
2479
|
+
let mult = PRACTICE_BASE_MULT;
|
|
2480
|
+
for (const tag of practiceTags) {
|
|
2481
|
+
if (cardsByTag.get(tag)?.includes(cardId) ?? false) {
|
|
2482
|
+
mult = Math.max(mult, tagMultiplier.get(tag) ?? PRACTICE_BASE_MULT);
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
const score = BASE_PRACTICE_SCORE * mult;
|
|
2424
2486
|
cards.push({
|
|
2425
2487
|
cardId,
|
|
2426
2488
|
courseId,
|
|
2427
|
-
score
|
|
2489
|
+
score,
|
|
2428
2490
|
provenance: [
|
|
2429
2491
|
{
|
|
2430
2492
|
strategy: "prescribed",
|
|
2431
2493
|
strategyName: this.strategyName || this.name,
|
|
2432
2494
|
strategyId: this.strategyId || "NAVIGATION_STRATEGY-prescribed",
|
|
2433
2495
|
action: "generated",
|
|
2434
|
-
score
|
|
2435
|
-
reason: `mode=practice;group=${group.id};underPracticedSkills=${practiceTags.length};practiceTags=${practiceTags.slice(0, 8).join("|")}${practiceTags.length > 8 ? "|\u2026" : ""};testversion=${PRESCRIBED_DEBUG_VERSION}`
|
|
2496
|
+
score,
|
|
2497
|
+
reason: `mode=practice;group=${group.id};debtMult=\xD7${mult.toFixed(2)};underPracticedSkills=${practiceTags.length};practiceTags=${practiceTags.slice(0, 8).join("|")}${practiceTags.length > 8 ? "|\u2026" : ""};testversion=${PRESCRIBED_DEBUG_VERSION}`
|
|
2436
2498
|
}
|
|
2437
2499
|
]
|
|
2438
2500
|
});
|
|
@@ -2606,14 +2668,15 @@ __export(srs_exports, {
|
|
|
2606
2668
|
default: () => SRSNavigator
|
|
2607
2669
|
});
|
|
2608
2670
|
import moment from "moment";
|
|
2609
|
-
var DEFAULT_HEALTHY_BACKLOG,
|
|
2671
|
+
var DEFAULT_HEALTHY_BACKLOG, MAX_BACKLOG_MULTIPLIER, SRSNavigator;
|
|
2610
2672
|
var init_srs = __esm({
|
|
2611
2673
|
"src/core/navigators/generators/srs.ts"() {
|
|
2612
2674
|
"use strict";
|
|
2613
2675
|
init_navigators();
|
|
2676
|
+
init_SrsDebugger();
|
|
2614
2677
|
init_logger();
|
|
2615
2678
|
DEFAULT_HEALTHY_BACKLOG = 20;
|
|
2616
|
-
|
|
2679
|
+
MAX_BACKLOG_MULTIPLIER = 2;
|
|
2617
2680
|
SRSNavigator = class extends ContentNavigator {
|
|
2618
2681
|
/** Human-readable name for CardGenerator interface */
|
|
2619
2682
|
name;
|
|
@@ -2680,9 +2743,18 @@ var init_srs = __esm({
|
|
|
2680
2743
|
}
|
|
2681
2744
|
}
|
|
2682
2745
|
}
|
|
2683
|
-
const
|
|
2746
|
+
const backlogMultiplier = this.computeBacklogMultiplier(dueReviews.length);
|
|
2747
|
+
const notDue = reviews.filter((r) => !now.isAfter(moment.utc(r.reviewTime)));
|
|
2748
|
+
let nextDueIn = null;
|
|
2749
|
+
if (notDue.length > 0) {
|
|
2750
|
+
const next = notDue.reduce(
|
|
2751
|
+
(a, b) => moment.utc(a.reviewTime).isBefore(moment.utc(b.reviewTime)) ? a : b
|
|
2752
|
+
);
|
|
2753
|
+
const until = moment.duration(moment.utc(next.reviewTime).diff(now));
|
|
2754
|
+
nextDueIn = until.asHours() < 1 ? `${Math.round(until.asMinutes())}m` : until.asHours() < 24 ? `${Math.round(until.asHours())}h` : `${Math.round(until.asDays())}d`;
|
|
2755
|
+
}
|
|
2684
2756
|
if (dueReviews.length > 0) {
|
|
2685
|
-
const pressureNote =
|
|
2757
|
+
const pressureNote = backlogMultiplier > 1 ? ` [backlog pressure: \xD7${backlogMultiplier.toFixed(2)}]` : ` [healthy backlog]`;
|
|
2686
2758
|
logger.info(
|
|
2687
2759
|
`[SRS] Course ${courseId}: ${dueReviews.length} reviews due now (of ${reviews.length} scheduled)${pressureNote}`
|
|
2688
2760
|
);
|
|
@@ -2701,7 +2773,7 @@ var init_srs = __esm({
|
|
|
2701
2773
|
logger.info(`[SRS] Course ${courseId}: No reviews scheduled`);
|
|
2702
2774
|
}
|
|
2703
2775
|
const scored = dueReviews.map((review) => {
|
|
2704
|
-
const { score, reason } = this.computeUrgencyScore(review, now,
|
|
2776
|
+
const { score, reason } = this.computeUrgencyScore(review, now, backlogMultiplier);
|
|
2705
2777
|
return {
|
|
2706
2778
|
cardId: review.cardId,
|
|
2707
2779
|
courseId: review.courseId,
|
|
@@ -2719,30 +2791,42 @@ var init_srs = __esm({
|
|
|
2719
2791
|
]
|
|
2720
2792
|
};
|
|
2721
2793
|
});
|
|
2722
|
-
|
|
2794
|
+
const sorted = scored.sort((a, b) => b.score - a.score);
|
|
2795
|
+
captureSrsBacklog({
|
|
2796
|
+
courseId,
|
|
2797
|
+
scheduledTotal: reviews.length,
|
|
2798
|
+
dueNow: dueReviews.length,
|
|
2799
|
+
healthyBacklog: this.healthyBacklog,
|
|
2800
|
+
backlogMultiplier,
|
|
2801
|
+
maxBacklogMultiplier: MAX_BACKLOG_MULTIPLIER,
|
|
2802
|
+
topReviewScore: sorted.length > 0 ? sorted[0].score : null,
|
|
2803
|
+
nextDueIn,
|
|
2804
|
+
timestamp: Date.now()
|
|
2805
|
+
});
|
|
2806
|
+
return { cards: sorted.slice(0, limit) };
|
|
2723
2807
|
}
|
|
2724
2808
|
/**
|
|
2725
|
-
* Compute backlog pressure based on number of due reviews.
|
|
2809
|
+
* Compute the multiplicative backlog pressure based on number of due reviews.
|
|
2726
2810
|
*
|
|
2727
|
-
*
|
|
2728
|
-
* and
|
|
2811
|
+
* ×1.0 at or below the healthy threshold (no boost), increasing linearly above
|
|
2812
|
+
* it and maxing out at MAX_BACKLOG_MULTIPLIER at 3× the healthy backlog.
|
|
2729
2813
|
*
|
|
2730
|
-
* Examples (with default healthyBacklog=20):
|
|
2731
|
-
* - 10 due reviews →
|
|
2732
|
-
* - 20 due reviews →
|
|
2733
|
-
* - 40 due reviews →
|
|
2734
|
-
* - 60 due reviews →
|
|
2814
|
+
* Examples (with default healthyBacklog=20, MAX_BACKLOG_MULTIPLIER=2.0):
|
|
2815
|
+
* - 10 due reviews → ×1.00 (healthy)
|
|
2816
|
+
* - 20 due reviews → ×1.00 (at threshold)
|
|
2817
|
+
* - 40 due reviews → ×1.50 (2x threshold)
|
|
2818
|
+
* - 60 due reviews → ×2.00 (3x threshold, maxed)
|
|
2735
2819
|
*
|
|
2736
2820
|
* @param dueCount - Number of reviews currently due
|
|
2737
|
-
* @returns
|
|
2821
|
+
* @returns Multiplier applied to review urgency (1.0 to MAX_BACKLOG_MULTIPLIER)
|
|
2738
2822
|
*/
|
|
2739
|
-
|
|
2823
|
+
computeBacklogMultiplier(dueCount) {
|
|
2740
2824
|
if (dueCount <= this.healthyBacklog) {
|
|
2741
|
-
return
|
|
2825
|
+
return 1;
|
|
2742
2826
|
}
|
|
2743
2827
|
const excess = dueCount - this.healthyBacklog;
|
|
2744
|
-
const
|
|
2745
|
-
return Math.min(
|
|
2828
|
+
const multiplier = 1 + excess / this.healthyBacklog * ((MAX_BACKLOG_MULTIPLIER - 1) / 2);
|
|
2829
|
+
return Math.min(MAX_BACKLOG_MULTIPLIER, multiplier);
|
|
2746
2830
|
}
|
|
2747
2831
|
/**
|
|
2748
2832
|
* Compute urgency score for a review card.
|
|
@@ -2757,19 +2841,20 @@ var init_srs = __esm({
|
|
|
2757
2841
|
* - 30 days (720h) → ~0.56
|
|
2758
2842
|
* - 180 days → ~0.30
|
|
2759
2843
|
*
|
|
2760
|
-
* 3. Backlog pressure = global
|
|
2761
|
-
*
|
|
2762
|
-
* - At 2x healthy: +0.25
|
|
2763
|
-
* - At 3x+ healthy: +0.50 (max)
|
|
2844
|
+
* 3. Backlog pressure = global *multiplier* when review backlog exceeds the
|
|
2845
|
+
* healthy threshold (×1.0 healthy → up to MAX_BACKLOG_MULTIPLIER at 3×).
|
|
2764
2846
|
*
|
|
2765
|
-
* Combined: base 0.5 +
|
|
2766
|
-
*
|
|
2847
|
+
* Combined: (base 0.5 + urgency factors * 0.45) × backlog multiplier.
|
|
2848
|
+
* Per-card range before pressure: ~0.57–0.95. NOT clamped to 1.0 — under a
|
|
2849
|
+
* heavy backlog reviews scale onto the open scale to compete with (and exceed)
|
|
2850
|
+
* new cards; what keeps them from running away is the bounded multiplier, not
|
|
2851
|
+
* a hard ceiling.
|
|
2767
2852
|
*
|
|
2768
2853
|
* @param review - The scheduled card to score
|
|
2769
2854
|
* @param now - Current time
|
|
2770
|
-
* @param
|
|
2855
|
+
* @param backlogMultiplier - Pre-computed backlog multiplier (1.0 to MAX_BACKLOG_MULTIPLIER)
|
|
2771
2856
|
*/
|
|
2772
|
-
computeUrgencyScore(review, now,
|
|
2857
|
+
computeUrgencyScore(review, now, backlogMultiplier) {
|
|
2773
2858
|
const scheduledAt = moment.utc(review.scheduledAt);
|
|
2774
2859
|
const due = moment.utc(review.reviewTime);
|
|
2775
2860
|
const intervalHours = Math.max(1, due.diff(scheduledAt, "hours"));
|
|
@@ -2779,15 +2864,15 @@ var init_srs = __esm({
|
|
|
2779
2864
|
const overdueContribution = Math.min(1, Math.max(0, relativeOverdue));
|
|
2780
2865
|
const urgency = overdueContribution * 0.5 + recencyFactor * 0.5;
|
|
2781
2866
|
const baseScore = 0.5 + urgency * 0.45;
|
|
2782
|
-
const score =
|
|
2867
|
+
const score = baseScore * backlogMultiplier;
|
|
2783
2868
|
const reasonParts = [
|
|
2784
2869
|
`${Math.round(hoursOverdue)}h overdue`,
|
|
2785
2870
|
`interval: ${Math.round(intervalHours)}h`,
|
|
2786
2871
|
`relative: ${relativeOverdue.toFixed(2)}`,
|
|
2787
2872
|
`recency: ${recencyFactor.toFixed(2)}`
|
|
2788
2873
|
];
|
|
2789
|
-
if (
|
|
2790
|
-
reasonParts.push(`backlog:
|
|
2874
|
+
if (backlogMultiplier > 1) {
|
|
2875
|
+
reasonParts.push(`backlog: \xD7${backlogMultiplier.toFixed(2)}`);
|
|
2791
2876
|
}
|
|
2792
2877
|
reasonParts.push("review");
|
|
2793
2878
|
const reason = reasonParts.join(", ");
|
|
@@ -4839,6 +4924,7 @@ var init_3 = __esm({
|
|
|
4839
4924
|
"./Pipeline.ts": () => Promise.resolve().then(() => (init_Pipeline(), Pipeline_exports)),
|
|
4840
4925
|
"./PipelineAssembler.ts": () => Promise.resolve().then(() => (init_PipelineAssembler(), PipelineAssembler_exports)),
|
|
4841
4926
|
"./PipelineDebugger.ts": () => Promise.resolve().then(() => (init_PipelineDebugger(), PipelineDebugger_exports)),
|
|
4927
|
+
"./SrsDebugger.ts": () => Promise.resolve().then(() => (init_SrsDebugger(), SrsDebugger_exports)),
|
|
4842
4928
|
"./defaults.ts": () => Promise.resolve().then(() => (init_defaults(), defaults_exports)),
|
|
4843
4929
|
"./diversityRerank.ts": () => Promise.resolve().then(() => (init_diversityRerank(), diversityRerank_exports)),
|
|
4844
4930
|
"./filters/WeightedFilter.ts": () => Promise.resolve().then(() => (init_WeightedFilter(), WeightedFilter_exports)),
|
|
@@ -4871,12 +4957,14 @@ __export(navigators_exports, {
|
|
|
4871
4957
|
NavigatorRole: () => NavigatorRole,
|
|
4872
4958
|
NavigatorRoles: () => NavigatorRoles,
|
|
4873
4959
|
Navigators: () => Navigators,
|
|
4960
|
+
clearSrsBacklogDebug: () => clearSrsBacklogDebug,
|
|
4874
4961
|
diversityRerank: () => diversityRerank,
|
|
4875
4962
|
getActivePipeline: () => getActivePipeline,
|
|
4876
4963
|
getCardOrigin: () => getCardOrigin,
|
|
4877
4964
|
getRegisteredNavigator: () => getRegisteredNavigator,
|
|
4878
4965
|
getRegisteredNavigatorNames: () => getRegisteredNavigatorNames,
|
|
4879
4966
|
getRegisteredNavigatorRole: () => getRegisteredNavigatorRole,
|
|
4967
|
+
getSrsBacklogDebug: () => getSrsBacklogDebug,
|
|
4880
4968
|
hasRegisteredNavigator: () => hasRegisteredNavigator,
|
|
4881
4969
|
initializeNavigatorRegistry: () => initializeNavigatorRegistry,
|
|
4882
4970
|
isFilter: () => isFilter,
|
|
@@ -4958,6 +5046,7 @@ var init_navigators = __esm({
|
|
|
4958
5046
|
"use strict";
|
|
4959
5047
|
init_diversityRerank();
|
|
4960
5048
|
init_PipelineDebugger();
|
|
5049
|
+
init_SrsDebugger();
|
|
4961
5050
|
init_logger();
|
|
4962
5051
|
init_();
|
|
4963
5052
|
init_2();
|