All files / src/lib derive-usage.ts

100% Statements 8/8
100% Branches 2/2
100% Functions 2/2
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24                          88x 52x   88x 88x 42x 42x   88x    
// Usage is DERIVED at read time (parent D3 — no projection table): the latest
// usage event per item wins, resolved by the ONE shared (createdAt, id)
// comparator the scorer already uses (parent ARCH-6), so every reader of usage
// (the Ranking's usage notes, saved rankings' stamps) agrees about "known".
import { compareByCreatedAtThenId } from "@/lib/decision-order";
import type { DecisionEvent, UsageDecision } from "@/types";
 
export type UsageAnswer = "uses" | "not_uses";
 
export function deriveUsage(
  events: readonly DecisionEvent[],
  liveItemIds: ReadonlySet<string>,
): Map<string, UsageAnswer> {
  const usage = events
    .filter((e) => e.type === "usage")
    .sort(compareByCreatedAtThenId);
  const byItem = new Map<string, UsageAnswer>();
  for (const e of usage) {
    const d = e.decision as UsageDecision;
    if (liveItemIds.has(d.itemId)) byItem.set(d.itemId, d.result);
  }
  return byItem;
}