`;
}).join("");
}
$("#build").textContent = `Store: ${fmtN(b.store.items)} items, saved ${b.store.saved ? ago(b.store.saved) : "not yet"} · model ${b.semantic.model} ${b.semantic.ready ? "ready" : "not loaded"} · up since ${stamp(b.store.booted)}`;
}
$("#checkBtn").addEventListener("click", async () => {
notice("");
try {
const { status, body } = await getJSON("api/check", { method: "POST" });
if (status === 429) { notice(esc(body.reason) + ". The collector also runs on its own schedule (Sources tab).", "warn"); return; }
if (status === 409) notice("A check is already running; following it.");
wasRunning = true; pollSources();
} catch (err) { notice("Could not start a check: " + esc(err.message), "bad"); }
});
/* ------------------------------------------------------------ KPIs */
function renderKpis() {
const o = S.ov, items = o.items;
const spark = SRC.filter((k) => o.by_source[k]).map((k) => ``).join("");
const bspark = BANDS.filter((b) => o.by_band[b]).map((b) => ``).join("");
const nNew = S.lastVisit ? S.items.filter((i) => (i.first_seen || "") > S.lastVisit).length : null;
const win = `in the last ${lbLabel(S.f.since)}`;
$("#kpis").innerHTML = [
`
Items${fmtN(items)}${esc(win)}
${spark}
`,
`
High relevance${fmtN(o.high)}score 60 or more; ${fmtN(o.medium)} medium
${bspark}
`,
`
With code or data${fmtN(o.with_code + o.new_repos)}${fmtN(o.with_code)} link code, ${fmtN(o.new_repos)} new repositories
`,
o.learned && o.learned.ready
? `
Learned scores${fmtN(o.learned.items)}scored by a model fitted to blind ratings of ${fmtN(o.learned.trained_on)} items
`
: `
Found by meaning${o.semantic.ready ? fmtN(o.lifted_by_meaning) : "off"}${o.semantic.ready ? "scored higher by the model than by keywords" : "the model is loading"}
`,
`
New since your visit${nNew == null ? "first" : fmtN(nNew)}${S.lastVisit ? "among the top items, since " + esc(stamp(S.lastVisit)) : "visit; marks start next time"}
`,
].join("");
}
/* ------------------------------------------------------------ charts */
function binLabel(iso, step) {
const d = D(iso);
if (step < 3600) return hm(d);
if (step < 86400) return d.getUTCHours() === 0 || step >= 6 * 3600 ? dm(d) + " " + hm(d) : hm(d);
return dm(d);
}
function chartTime() {
const host = $("#chTime"); host.innerHTML = "";
const tl = S.ov.timeline, bins = tl.bins, step = tl.bin_seconds;
const unit = step < 3600 ? (step / 60) + "-minute" : step < 86400 ? (step / 3600) + "-hour" : "day";
$("#tlCaption").textContent = `Items per ${unit} bin (UTC), by ${S.f.by === "found" ? "when the radar found them" : "publish or update time"}, stacked by source.`;
const W = width(host, 320, 1140), H = W < 600 ? 210 : 230, L = 38, R = 10, T = 16, B = 28;
const tot = (b) => SRC.reduce((a, k) => a + (b.n[k] || 0), 0);
const max = niceMax(Math.max(1, ...bins.map(tot)));
const svg = el("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": "Items per time bin, stacked by source" });
const y = (v) => T + (H - T - B) * (1 - v / max);
ticks(max, 4).forEach((v) => { svg.appendChild(el("line", { x1: L, x2: W - R, y1: y(v), y2: y(v), class: v === 0 ? "base" : "gl" })); svg.appendChild(el("text", { x: L - 7, y: y(v) + 3.5, "text-anchor": "end", class: "tick" }, fmtN(v))); });
const bw = (W - L - R) / bins.length, w = Math.max(1.5, Math.min(40, bw * 0.7));
const every = Math.ceil(bins.length / Math.max(3, Math.floor((W - L) / 84)));
bins.forEach((b, n) => {
const cx = L + bw * n + bw / 2, t = tot(b);
const present = SRC.filter((k) => b.n[k]);
let acc = 0;
present.forEach((k, j) => {
const y0 = y(acc), y1 = y(acc + b.n[k]); acc += b.n[k];
const top = j === present.length - 1, gap = top || w < 4 ? 0 : 1.5;
const h = Math.max(0, y0 - y1 - gap);
svg.appendChild(el("path", { d: top ? barPath(cx - w / 2, y1, w, h, Math.min(3, w / 2)) : `M${cx - w / 2},${y1 + gap}h${w}v${h}h${-w}Z`, style: `fill:var(--s-${k})`, class: "mark" }));
});
if (t && bins.length <= 40) svg.appendChild(el("text", { x: cx, y: y(t) - 5, "text-anchor": "middle", class: "tick", style: "fill:var(--fg2)" }, fmtN(t)));
if (n % every === 0) svg.appendChild(el("text", { x: cx, y: H - 9, "text-anchor": "middle", class: "tick" }, binLabel(b.t, step)));
const end = new Date(D(b.t).getTime() + step * 1000).toISOString();
svg.appendChild(el("rect", { x: L + bw * n, y: T, width: bw, height: H - T - B, class: "hit", "data-tip": `${esc(stamp(b.t))} to ${esc(hm(D(end)))}` + (t ? SRC.filter((k) => b.n[k]).map((k) => row(`var(--s-${k})`, SRC_LABEL[k], b.n[k])).join("") : hint("Nothing in this bin")) + (t ? row("", "Total", t) : "") }));
});
if (!S.ov.items) svg.appendChild(el("text", { x: W / 2, y: H / 2, "text-anchor": "middle", class: "empty" }, "Nothing in this window yet"));
host.appendChild(svg);
$("#legTime").innerHTML = SRC.filter((k) => S.ov.by_source[k]).map((k) => `${SRC_LABEL[k]}`).join("");
}
function chartTopics() {
const host = $("#chTopics"); host.innerHTML = "";
const rows = Object.entries(S.ov.by_topic).slice(0, 10);
const W = width(host, 300, 520), rowH = 30, L = 156, R = 40, H = Math.max(70, rows.length * rowH + 8);
const max = Math.max(1, ...rows.map((r) => r[1]));
const svg = el("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": "Items per topic" });
host.classList.toggle("dim", S.f.topics.length > 0);
rows.forEach(([t, n], k) => {
const y = 4 + k * rowH, w = (W - L - R) * n / max, on = S.f.topics.includes(t);
svg.appendChild(el("text", { x: L - 10, y: y + rowH / 2 + 4, "text-anchor": "end", "font-size": 12.5, style: on ? "fill:var(--fg);font-weight:650" : "" }, t));
svg.appendChild(el("path", { d: barPath(L, y + 7, Math.max(3, w), rowH - 14, 4, true), class: "mark" + (on ? " on" : ""), style: "fill:var(--accent)" }));
svg.appendChild(el("text", { x: L + w + 7, y: y + rowH / 2 + 4, class: "tick", style: "fill:var(--fg2)" }, fmtN(n)));
const hit = el("rect", { x: 0, y, width: W, height: rowH, class: "hit", "data-tip": `${esc(t)}` + row("", "Items", fmtN(n)) + hint(on ? "Click to remove this filter" : "Click to filter by this topic") });
hit.addEventListener("click", () => toggle("topics", t));
svg.appendChild(hit);
});
if (!rows.length) svg.appendChild(el("text", { x: W / 2, y: 38, "text-anchor": "middle", class: "empty" }, "No topics in view"));
host.appendChild(svg);
}
function chartScores() {
const host = $("#chScores"); host.innerHTML = "";
const bins = S.base.score_hist;
const W = width(host, 300, 520), H = 240, L = 34, R = 8, T = 14, B = 28;
const max = niceMax(Math.max(1, ...bins));
const svg = el("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": "Histogram of relevance scores" });
const y = (v) => T + (H - T - B) * (1 - v / max), x = (s) => L + (W - L - R) * s / 100;
ticks(max, 3).forEach((v) => { svg.appendChild(el("line", { x1: L, x2: W - R, y1: y(v), y2: y(v), class: v === 0 ? "base" : "gl" })); svg.appendChild(el("text", { x: L - 6, y: y(v) + 3.5, "text-anchor": "end", class: "tick" }, fmtN(v))); });
const band = (a) => (a >= 60 ? "high" : a >= 35 ? "medium" : "low");
bins.forEach((n, k) => {
const a = k * 5, x0 = x(a) + 1, w = x(a + 5) - x(a) - 2;
if (n) svg.appendChild(el("path", { d: barPath(x0, y(n), w, y(0) - y(n), 3), style: `fill:var(--b-${band(a)})`, opacity: a + 5 <= S.f.min ? 0.3 : 1 }));
const hit = el("rect", { x: x0, y: T, width: w, height: H - T - B, class: "hit", "data-tip": `Score ${a} to ${a + 4}` + row(`var(--b-${band(a)})`, BAND_LABEL[band(a)] + " band", fmtN(n) + " items") + hint("Click to set the minimum score here") });
hit.addEventListener("click", () => { S.f.min = Math.min(90, a); reload(); });
svg.appendChild(hit);
});
[0, 20, 35, 60, 80, 100].forEach((v) => svg.appendChild(el("text", { x: x(v), y: H - 9, "text-anchor": "middle", class: "tick" }, v)));
const mx = x(S.f.min);
svg.appendChild(el("line", { x1: mx, x2: mx, y1: T - 4, y2: y(0), style: "stroke:var(--fg);stroke-width:1.5", "stroke-dasharray": "4 3" }));
svg.appendChild(el("text", { x: mx + 5, y: T + 7, "font-size": 11, style: "fill:var(--fg)" }, "min " + S.f.min));
host.appendChild(svg);
}
function chartSources() {
const host = $("#chSources"); host.innerHTML = "";
const by = S.base.by_source, rows = SRC.map((k) => [k, by[k] || 0]);
const W = width(host, 300, 520), rowH = 30, L = 120, R = 44, H = rows.length * rowH + 6;
const max = Math.max(1, ...rows.map((r) => r[1]));
const svg = el("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": "Items per source" });
host.classList.toggle("dim", S.f.sources.length > 0);
rows.forEach(([k, n], j) => {
const y = 3 + j * rowH, w = (W - L - R) * n / max, on = S.f.sources.includes(k);
svg.appendChild(el("circle", { cx: 8, cy: y + rowH / 2, r: 5, style: `fill:var(--s-${k})` }));
svg.appendChild(el("text", { x: 20, y: y + rowH / 2 + 4, "font-size": 13, style: on ? "fill:var(--fg);font-weight:650" : "fill:var(--fg)" }, SRC_LABEL[k]));
svg.appendChild(el("rect", { x: L, y: y + 8, width: W - L - R, height: rowH - 16, rx: 4, style: "fill:var(--chip)" }));
if (n) svg.appendChild(el("path", { d: barPath(L, y + 8, Math.max(3, w), rowH - 16, 4, true), class: "mark" + (on ? " on" : ""), style: `fill:var(--s-${k})` }));
svg.appendChild(el("text", { x: W - R + 8, y: y + rowH / 2 + 4, class: "tick", style: "fill:var(--fg2)" }, fmtN(n)));
const hit = el("rect", { x: 0, y, width: W, height: rowH, class: "hit", "data-tip": `${SRC_LABEL[k]}` + row(`var(--s-${k})`, "Items in view", fmtN(n)) + hint(on ? "Click to remove this filter" : "Click to show only this source") });
hit.addEventListener("click", () => toggle("sources", k));
svg.appendChild(hit);
});
host.appendChild(svg);
}
function mix(t) { // a share of the heat ramp, as a CSS color-mix
return `color-mix(in oklab, var(--heat-1) ${Math.round(12 + 88 * t)}%, var(--heat-0))`;
}
function chartMatrix() {
const host = $("#chMatrix"); host.innerHTML = "";
const m = S.ov.topic_source, topics = Object.keys(S.ov.by_topic).slice(0, 9), srcs = SRC.filter((k) => S.ov.by_source[k]);
if (!topics.length) { host.innerHTML = '
No items in view.
'; return; }
const W = width(host, 320, 560), L = 150, T = 26, cw = (W - L - 4) / Math.max(1, srcs.length), ch = 26, H = T + topics.length * ch + 4;
const max = Math.max(1, ...topics.flatMap((t) => srcs.map((k) => (m[t] || {})[k] || 0)));
const svg = el("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": "Items per topic and source" });
srcs.forEach((k, j) => svg.appendChild(el("text", { x: L + cw * j + cw / 2, y: 14, "text-anchor": "middle", "font-size": 11.5 }, (cw < 60 ? SHORT : SRC_LABEL)[k])));
topics.forEach((t, i) => {
const y = T + i * ch;
svg.appendChild(el("text", { x: L - 10, y: y + ch / 2 + 4, "text-anchor": "end", "font-size": 12.5 }, t));
srcs.forEach((k, j) => {
const n = (m[t] || {})[k] || 0, x = L + cw * j;
svg.appendChild(el("rect", { x: x + 1, y: y + 1, width: cw - 2, height: ch - 2, rx: 4, style: `fill:${n ? mix(Math.sqrt(n / max)) : "var(--sunk)"}`, "data-tip": `${esc(t)}` + row(`var(--s-${k})`, SRC_LABEL[k], fmtN(n) + " items") }));
if (n && cw > 30) svg.appendChild(el("text", { x: x + cw / 2, y: y + ch / 2 + 4, "text-anchor": "middle", class: "tick", style: n / max > 0.45 ? "fill:var(--surface);pointer-events:none" : "fill:var(--fg);pointer-events:none" }, fmtN(n)));
});
});
host.appendChild(svg);
}
function chartPeople() {
const host = $("#chPeople"); host.innerHTML = "";
const rows = (S.ov.people || Object.entries(S.ov.top_people).map(([name, value]) => ({ name, value, works: null, items: null }))).slice(0, 8);
if (!rows.length) { host.innerHTML = '
No authors in view.
'; return; }
const W = width(host, 320, 560), rowH = 30, L = Math.min(210, W * 0.42), R = 96, H = rows.length * rowH + 6;
const max = Math.max(1, ...rows.map((r) => r.value));
const svg = el("svg", { viewBox: `0 0 ${W} ${H}`, role: "img", "aria-label": "Top contributors by pieces of work" });
rows.forEach((r, k) => {
const y = 3 + k * rowH, w = (W - L - R) * r.value / max, p = r.name;
const name = p.length > 28 ? p.slice(0, 26) + "..." : p;
const works = r.works == null ? "" : `${r.works} ${r.works === 1 ? "piece" : "pieces"}`;
svg.appendChild(el("text", { x: L - 10, y: y + rowH / 2 + 4, "text-anchor": "end", "font-size": 12.5 }, name));
svg.appendChild(el("path", { d: barPath(L, y + 8, Math.max(3, w), rowH - 16, 4, true), style: "fill:var(--b-medium)" }));
svg.appendChild(el("text", { x: L + w + 7, y: y + rowH / 2 + 4, class: "tick", style: "fill:var(--fg2)" }, works || fmtN(r.value)));
const tipHtml = `${esc(p)}` + (r.works != null ? row("", "Pieces of work", fmtN(r.works)) + row("", "Items", fmtN(r.items)) : "") +
row("", "Weight (best score per piece, summed)", fmtN(r.value)) + hint("Click to search for this name");
const hit = el("rect", { x: 0, y, width: W, height: rowH, class: "hit", "data-tip": tipHtml });
hit.addEventListener("click", () => { S.f.q = p; S.f.meaning = false; reload(); });
svg.appendChild(hit);
});
host.appendChild(svg);
}
/* ------------------------------------------------------------ filters */
// Sources, topics, relevance and the browser-only toggles sit in four small dropdowns; what is switched on shows as
// removable pills under them, so the panel stays one row however many filters exist.
function opt(group, value, label, n, extra, title) {
const on = group === "toggle" ? S.f[value] : S.f[group].includes(value);
return ``;
}
const TOGGLES = { code: "Links code", starred: "Starred", showHidden: "Show hidden", newOnly: "New since your visit" };
function summary(sel, all, label) {
if (!sel.length) return "";
return sel.length === 1 ? label(sel[0]) : `${sel.length} of ${all}`;
}
function renderFilters() {
const b = S.base;
// Only what this window holds, plus anything already picked, so the lists carry no rows of zeros.
const srcs = SRC.filter((k) => b.by_source[k] || S.f.sources.includes(k));
$("#fSources").innerHTML = srcs.map((k) => opt("sources", k, SRC_LABEL[k], b.by_source[k] || 0, ``)).join("") ||
'
The final score comes from the learned model, fitted to blind ratings of what items are worth to scroll work; it reads the ${i.learned === "full" ? "text's meaning, " : ""}keyword score, source, kind and popularity. The keyword points above explain the match; they no longer set the score.
` : ""}${i.capped ? `
Capped at ${i.score}: ${esc(i.capped)}.
` : ""}`;
}
function visible() {
let items = S.items.filter((i) => S.f.showHidden || !S.hide.has(i.id));
if (S.f.newOnly && S.lastVisit) items = items.filter((i) => (i.first_seen || "") > S.lastVisit);
return items;
}
function renderList() {
const items = visible();
const hiddenHere = S.items.length - S.items.filter((i) => !S.hide.has(i.id)).length;
$("#count").innerHTML = `${fmtN(S.matched)} items match` + (S.byMeaning ? ", closest in meaning to your words first" : "") + (hiddenHere && !S.f.showHidden ? ` · ${fmtN(hiddenHere)} hidden` : "");
if (!items.length) {
const short = /^(1|5|15|30)m$/.test(S.f.since);
$("#list").innerHTML = `
Nothing here yet.${short ? "Short windows are often empty: papers arrive once a day and the collector checks GitHub and Hugging Face every 20 minutes. Try " : "Lower the minimum score, widen the lookback or "}
`;
$("#pager").innerHTML = "";
return;
}
$("#list").innerHTML = items.map(itemHTML).join("");
$("#pager").innerHTML = pagerHTML();
$$("[data-similar]:not([hidden])").forEach((d) => loadSims(d.closest(".item").dataset.id, d));
}
$("#pager").addEventListener("click", (e) => { const b = e.target.closest("[data-page]"); if (b && !b.disabled) goPage(+b.dataset.page).catch(fail); });
$("#list").addEventListener("click", (e) => {
const q = e.target.closest("[data-quick]");
if (q) {
if (q.dataset.quick === "1d") { S.f.since = "1d"; renderLookback(); } else if (q.dataset.quick === "found") { S.f.by = "found"; renderLookback(); } else { const keep = { view: S.f.view, since: S.f.since }; S.f = Object.assign(defaults(), keep); }
reload(); return;
}
const card = e.target.closest(".item");
if (!card) return;
const id = card.dataset.id, item = S.items.find((x) => x.id === id);
const t = e.target.closest("[data-topic]");
if (t) { if (!S.f.topics.includes(t.dataset.topic)) toggle("topics", t.dataset.topic); return; }
if (e.target.closest(".summary, .usaid")) { e.target.closest(".summary, .usaid").classList.toggle("open"); return; }
const a = e.target.closest("[data-act]");
if (!a || !item) return;
const act = a.dataset.act;
if (act === "star") { S.stars.has(id) ? S.stars.delete(id) : S.stars.add(id); store.set("stars", Array.from(S.stars)); renderFilters(); renderList(); }
if (act === "hide") { S.hide.has(id) ? S.hide.delete(id) : S.hide.add(id); store.set("hidden", Array.from(S.hide)); renderFilters(); renderList(); }
if (act === "copy") { (navigator.clipboard ? navigator.clipboard.writeText(item.url) : Promise.reject()).then(() => { a.innerHTML = ICON.ok; setTimeout(() => (a.innerHTML = ICON.copy), 1200); }).catch(() => {}); }
// Each button opens and closes its own panel: the score's breakdown, or the nearest items in meaning.
if (act === "why") {
const d = card.querySelector("[data-detail]");
if (d.hidden) { S.open.add(id); d.innerHTML = whyHTML(item); d.hidden = false; } else { S.open.delete(id); d.hidden = true; }
a.setAttribute("aria-expanded", String(!d.hidden));
}
if (act === "like") {
const d = card.querySelector("[data-similar]");
if (d.hidden) { S.like.add(id); d.hidden = false; loadSims(id, d, true); } else { S.like.delete(id); d.hidden = true; }
a.setAttribute("aria-expanded", String(!d.hidden));
}
});
const simCache = {};
async function loadSims(id, box, scroll) {
box.innerHTML = '
Nothing scores 35 or more in this window.Widen the lookback above, or switch to Everyone.
`;
}
/* ------------------------------------------------------------ sources tab */
const SRC_ABOUT = {
arxiv: (c) => [`Today's announcement for ${c.rss.join(", ")}, with abstracts`, `Past-week lists of ${c.pastweek.join(", ")} once a day, to catch up after sleep`, "A search of every category for scroll terms"],
github: (c) => [`Repository searches: ${c.queries.join("; ")}`, `Pull requests, issues and releases of ${c.watch_repos.join(", ")}`, "Logged out; unchanged listings answered from cache"],
hf: (c) => [`Models, datasets and Spaces matching ${c.search.join(", ")}`, `Everything by ${c.authors.join(", ")}`, "Daily papers, merged with their arXiv rows"],
pypi: (c) => [`New versions of ${Object.keys(c.packages).length} packages: ${Object.keys(c.packages).join(", ")}`, "Pre-releases score 10 lower"],
zenodo: (c) => [`Records matching ${c.queries.join("; ")}`, "Datasets, software, preprints and articles"],
journals: (c) => [`Crossref works created in the window matching ${c.queries.join("; ")}`, "Journal articles, chapters, proceedings and posted content"],
blog: (c) => [`The feeds of ${[...new Set(c.feeds.map((f) => f.name || f[0]))].join(", ")}`, "News searches go through the scorer like any listing, and a story found twice is kept once"],
};
function renderSources() {
const b = S.src;
if (!b) return;
$("#srcTable tbody").innerHTML = SRC.map((k) => {
const v = b.sources[k];
return `
Learned modelrank agreement ${c.learned.evaluation.full.spearman} on held-out items
Ridge regression on the embedding plus ${esc(c.learned.meta_features.join(", "))}, source and kind; fitted ${esc(c.learned.trained)} to blind ratings of ${fmtN(c.learned.items)} items, ${esc(c.learned.calibration)} calibration to 0 to 100. The keyword and meaning scores alone agreed ${c.learned.evaluation.rule_score} with the same ratings.
` : "") +
`
Meaning anchorscosine ${c.semantic.sim_floor} to ${c.semantic.sim_ceiling} maps to 0 to 100