@vue-skuilder/db 0.2.5 → 0.2.7

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.
@@ -1161,9 +1161,22 @@ export class SessionController<TView = unknown> extends Loggable {
1161
1161
  // additive merge, or a stale generator candidate. This is the general guard
1162
1162
  // (see _servedCardIds); it makes re-presentation structurally impossible
1163
1163
  // rather than relying on each upstream path to exclude correctly.
1164
- const newWeighted = mixedWeighted
1165
- .filter((w) => getCardOrigin(w) === 'new' && !this._servedCardIds.has(w.cardId))
1166
- .slice(0, newLimit);
1164
+ const newCandidates = mixedWeighted.filter(
1165
+ (w) => getCardOrigin(w) === 'new' && !this._servedCardIds.has(w.cardId)
1166
+ );
1167
+ // `+INF` is the hard "include at all costs" sentinel applied by require*
1168
+ // injection (see Pipeline.applyRequirement). Partition these mandatory cards
1169
+ // to the front and exempt them from the newLimit slice, so neither the
1170
+ // mixer's source-shuffle/round-robin nor the cap can bury or drop a required
1171
+ // card before it reaches newQ. The set is also handed to mergeToFront so an
1172
+ // already-queued required card gets re-fronted rather than leapfrogged.
1173
+ const mandatoryWeighted = newCandidates.filter((w) => w.score === Number.POSITIVE_INFINITY);
1174
+ const optionalWeighted = newCandidates.filter((w) => w.score !== Number.POSITIVE_INFINITY);
1175
+ const newWeighted = [
1176
+ ...mandatoryWeighted,
1177
+ ...optionalWeighted.slice(0, Math.max(0, newLimit - mandatoryWeighted.length)),
1178
+ ];
1179
+ const mandatoryIds = new Set(mandatoryWeighted.map((w) => w.cardId));
1167
1180
 
1168
1181
  logger.debug(`[reviews] got ${reviewWeighted.length} reviews from mixer`);
1169
1182
 
@@ -1206,8 +1219,10 @@ export class SessionController<TView = unknown> extends Loggable {
1206
1219
  }
1207
1220
 
1208
1221
  if (additive) {
1209
- // Additive replan: merge new candidates into front of existing queue
1210
- const added = this.newQ.mergeToFront(newItems, (item) => item.cardID);
1222
+ // Additive replan: merge new candidates into front of existing queue.
1223
+ // Pass mandatory (+INF) ids so an already-queued required card is pulled
1224
+ // back to the front instead of being buried by fresh non-required cards.
1225
+ const added = this.newQ.mergeToFront(newItems, (item) => item.cardID, mandatoryIds);
1211
1226
  report += `Additive merge: ${added} new cards added to front of newQ\n`;
1212
1227
  } else if (replan) {
1213
1228
  // Atomic swap: replace entire newQ contents at once (no empty-queue window)