// BOS Staffing Market Scanner // Based on the open-jobs / JobScream local-first client (github.com/elliottdehn/open-jobs). // Flow: requisition text -> /embed -> descend the cluster manifest -> keep/skip clusters -> // live logistic regression over the downloaded pool -> ranked openings, company rollup, CSV. // Everything after the single /embed call runs in this tab. const API = "https://backend.dehnbostele.workers.dev"; const $ = (s) => document.querySelector(s); const state = { vec: null, manifest: null, cent: null, cards: [], decided: new Map(), pool: [], labels: new Map(), w: null, b: 0, shown: 0, dl: { done: 0, total: 0 }, view: "jobs" }; function show(step) { document.querySelectorAll(".step").forEach((e) => e.classList.remove("active")); $(step).classList.add("active"); const n = Number(step.slice(2)); for (let i = 1; i <= 3; i++) { const r = $("#r" + i); r.className = "rn" + (i === n ? " on" : i < n ? " done" : ""); } window.scrollTo({ top: 0, behavior: "smooth" }); } function norm(v) { let s = 0; for (const x of v) s += x * x; s = Math.sqrt(s) || 1; return Float32Array.from(v, (x) => x / s); } function vec(j) { const s = atob(j.v); const buf = new ArrayBuffer(s.length); const u = new Uint8Array(buf); for (let i = 0; i < s.length; i++) u[i] = s.charCodeAt(i); return new Float32Array(buf); } function dot(a, b) { let s = 0; for (let i = 0; i < a.length; i++) s += a[i] * b[i]; return s; } function esc(s) { return String(s ?? "").replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ }[c])); } // Employer labels come from whatever the board exposes. Hex client keys and GUIDs carry no name, // so those postings are labelled honestly and the recruiter clicks through. const HEX = /^[0-9a-f]{20,}$/i, GUID = /^[0-9a-f-]{30,}$/i; function pretty(s) { return String(s || "").replace(/[-_]+/g, " ").replace(/\b\w/g, (m) => m.toUpperCase()).trim(); } function coName(c) { const v = String(c || "").trim(); if (!v || HEX.test(v) || GUID.test(v)) return ""; if (v.includes(".")) return pretty(v.split(".")[0]); return /[\s]/.test(v) || v !== v.toLowerCase() ? v : pretty(v); } function co(j) { const c = String(j.company || "").trim(); if (c && !HEX.test(c) && !GUID.test(c) && !c.includes(".")) return /[\s.]/.test(c) || c !== c.toLowerCase() ? c : pretty(c); const slug = String(j.slug || ""); if (HEX.test(slug) || GUID.test(slug)) return "Employer not listed"; if (slug.includes(".")) return pretty(slug.split(".")[0]); // workday / oraclecloud hostnames return pretty(slug) || "Employer not listed"; } function say(el, msg, err) { const e = $(el); e.textContent = msg; e.className = "status" + (err ? " err" : ""); } // ---------- index ---------- async function readWithProgress(res, onPct) { const total = Number(res.headers.get("content-length")) || 0; if (!res.body || !total) return res.arrayBuffer(); const reader = res.body.getReader(); const chunks = []; let got = 0; for (;;) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); got += value.length; onPct(Math.round((100 * got) / total)); } const out = new Uint8Array(got); let o = 0; for (const c of chunks) { out.set(c, o); o += c.length; } return out.buffer; } async function loadManifest() { if (state.manifest) return; say("#st1", "Loading job index, this runs once per browser…"); const [mr, cr] = await Promise.all([fetch(`${API}/data/manifest.json`), fetch(`${API}/data/centroids.bin`)]); if (!mr.ok || !cr.ok) throw new Error(mr.status === 404 ? "The job index has not been published yet. Try again shortly." : `Could not load the job index (HTTP ${mr.status}).`); const cbuf = await readWithProgress(cr, (p) => say("#st1", `Loading job index… ${p}%`)); const m = await mr.json(); state.manifest = m; const u16 = new Uint16Array(cbuf), f = new Float32Array(u16.length); for (let i = 0; i < u16.length; i++) f[i] = f16(u16[i]); state.cent = f; $("#corpus").textContent = `${m.jobs.toLocaleString()} open postings · ${m.leaves.toLocaleString()} clusters\n${m.recipe}`; $("#corpus").style.whiteSpace = "pre"; } function f16(h) { const s = (h & 0x8000) ? -1 : 1, e = (h >> 10) & 0x1f, m = h & 0x3ff; if (e === 0) return s * m * 2 ** -24; if (e === 31) return m ? NaN : s * Infinity; return s * (1 + m / 1024) * 2 ** (e - 15); } function centroid(i) { const d = state.manifest.dims; return state.cent.subarray(i * d, (i + 1) * d); } function nearestNodes(q, want) { const T = state.manifest.tree, leaves = []; for (const n of T) if (!n.children.length) leaves.push([dot(q, centroid(n.id)), n]); leaves.sort((a, b) => b[0] - a[0]); return leaves.slice(0, want).map(([, n]) => n); } function leavesUnder(n) { const T = state.manifest.tree, out = [], st = [n]; while (st.length) { const x = st.pop(); if (!x.children.length) out.push(x); else for (const c of x.children) st.push(T[c]); } return out; } // ---------- step 1 ---------- $("#go").onclick = async () => { const text = $("#resume").value.trim(); if (text.length < 20) { say("#st1", "Add a bit more detail before scanning.", true); return; } $("#go").disabled = true; try { await loadManifest(); say("#st1", "Matching against the index…"); const r = await fetch(`${API}/embed`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ text, title: $("#title").value, location: $("#loc").value }) }); if (!r.ok) { const e = await r.json().catch(() => ({})); throw new Error(e.error ? `${e.error}${e.retryAfterSeconds ? `. Retry in ${e.retryAfterSeconds}s.` : ""}` : `Request failed (HTTP ${r.status}).`); } const { vector, recipe } = await r.json(); state.vec = norm(vector); say("#st1", recipe !== state.manifest.recipe ? `Heads up: index recipe ${state.manifest.recipe} does not match ${recipe}.` : ""); renderCards(24); show("#s2"); } catch (e) { say("#st1", String(e.message || e), true); } $("#go").disabled = false; }; // ---------- step 2 ---------- function renderCards(want) { state.cards = nearestNodes(state.vec, want); const el = $("#cards"); el.innerHTML = ""; for (const n of state.cards) { const sim = dot(state.vec, centroid(n.id)); const d = document.createElement("div"); d.className = "card " + (state.decided.get(n.id) || ""); d.innerHTML = `
${esc(n.label || n.medoid)}
${n.size.toLocaleString()} openings${n.distinct_titles ? ` · ${n.distinct_titles} distinct titles` : ""} · match ${sim.toFixed(2)} · spread ${n.radius.toFixed(2)}
`; d.querySelector(".btn-yes").onclick = () => decide(n, "maybe", d); d.querySelector(".btn-no").onclick = () => decide(n, "no", d); el.appendChild(d); } } $("#more").onclick = () => renderCards(state.cards.length + 24); function decide(n, v, el) { state.decided.set(n.id, v); el.className = "card " + v; if (v === "maybe") for (const leaf of leavesUnder(n)) fetchGroup(leaf); $("#next2").disabled = ![...state.decided.values()].includes("maybe"); } const groups = new Map(); async function fetchGroup(leaf) { if (groups.has(leaf.id)) return; groups.set(leaf.id, null); state.dl.total++; updDl(); const gr = await fetch(`${API}/data/groups/${leaf.id}.json`); if (!gr.ok) { groups.delete(leaf.id); state.dl.total--; updDl(); return; } const g = await gr.json(); for (const j of g.jobs) { j.v = vec(j); j.leaf = leaf.id; j.sim = dot(state.vec, j.v); state.pool.push(j); } groups.set(leaf.id, g); state.dl.done++; updDl(); } function updDl() { $("#dl").textContent = state.dl.total ? `${state.dl.done} of ${state.dl.total} clusters downloaded · ${state.pool.length.toLocaleString()} openings held locally` : ""; $("#dlbar").style.width = state.dl.total ? `${(100 * state.dl.done) / state.dl.total}%` : "0"; } $("#next2").onclick = () => { seedNegatives(); refit(); render(true); show("#s3"); }; // ---------- step 3 ---------- function seedNegatives() { for (const [id, v] of state.decided) if (v === "no") { const n = state.manifest.tree[id]; for (const leaf of leavesUnder(n).slice(0, 2)) fetch(`${API}/data/groups/${leaf.id}.json`).then((r) => r.json()).then((g) => { for (const j of g.jobs.slice(0, 5)) { j.v = vec(j); j.neg = true; j.sim = dot(state.vec, j.v); state.pool.push(j); state.labels.set(key(j), 0); } refit(); render(false); }).catch(() => {}); } } const key = (j) => `${j.ats}/${j.slug}#${j.id}`; function refit() { const D = state.manifest.dims, items = state.pool.filter((j) => state.labels.has(key(j))); const pos = items.filter((j) => state.labels.get(key(j)) === 1).length, neg = items.length - pos; if (pos === 0 || neg === 0) { state.w = null; say("#st3", `Ranked by requisition match. Mark at least one keep and one drop to train the model. Currently ${pos} keep / ${neg} drop.`); return; } const w = Float32Array.from(state.vec); let b = 0; const lr = 0.5, l2 = 0.01; for (let ep = 0; ep < 30; ep++) for (const j of items) { const y = state.labels.get(key(j)), p = 1 / (1 + Math.exp(-(dot(w, j.v) + b))), g = p - y; for (let i = 0; i < D; i++) w[i] -= lr * (g * j.v[i] + l2 * (w[i] - state.vec[i])); b -= lr * g; } state.w = w; state.b = b; say("#st3", `Model trained on ${pos} keep / ${neg} drop · ${state.pool.length.toLocaleString()} openings ranked locally`); } function score(j) { return state.w ? 1 / (1 + Math.exp(-(dot(state.w, j.v) + state.b))) : j.sim; } let ranked = [], cur = 0; function render(reset) { ranked = state.pool.filter((j) => !j.neg).sort((a, b) => score(b) - score(a)); if (reset) state.shown = 0; state.view === "jobs" ? renderJobs() : renderCos(); } function renderJobs() { const el = $("#jobs"); el.innerHTML = ""; if (!ranked.length) { el.innerHTML = `
No openings loaded. Go back and keep at least one cluster.
`; return; } const N = Math.min(ranked.length, state.shown + 40); for (let i = 0; i < N; i++) el.appendChild(jobEl(ranked[i], i)); state.shown = N; cur = Math.min(cur, N - 1); hi(); } function jobEl(j, i) { const d = document.createElement("div"), l = state.labels.get(key(j)), s = score(j); d.className = "job " + (l === 1 ? "pos" : l === 0 ? "neg" : ""); d.dataset.i = i; d.innerHTML = `
${esc(j.title)}
${esc(co(j))}
${j.location ? esc(j.location) + " · " : ""}open posting
${esc(j.jd || "(no description on file)")}
${s.toFixed(2)}
`; d.querySelector("a").onclick = (e) => e.stopPropagation(); d.onclick = () => { cur = i; hi(); const x = d.querySelector(".jd"); x.style.display = x.style.display === "block" ? "none" : "block"; }; return d; } function hi() { document.querySelectorAll(".job").forEach((e, i) => e.classList.toggle("cur", i === cur)); const e = document.querySelector(`.job[data-i="${cur}"]`); if (e) e.scrollIntoView({ block: "nearest" }); } // Board-level rollup: one row per hiring board, which is one employer. Names come from the // backend's company resolution when it has run for that board (opt-in, ~2 KB per board). function rollup() { const by = new Map(); for (const j of ranked) { const k = `${j.ats}/${j.slug}`; const c = by.get(k) || { name: co(j), ats: j.ats, n: 0, best: 0, locs: new Set(), url: j.url }; c.n++; c.best = Math.max(c.best, score(j)); if (j.location) c.locs.add(j.location); by.set(k, c); } return [...by.values()].sort((a, b) => b.n - a.n || b.best - a.best); } function renderCos() { const rows = rollup().slice(0, 150); const el = $("#cos"); el.innerHTML = ""; if (!rows.length) { el.innerHTML = `
No openings loaded yet.
`; return; } for (const c of rows) { const locs = [...c.locs].slice(0, 3).join(" · ") + (c.locs.size > 3 ? ` +${c.locs.size - 3} more` : ""); const d = document.createElement("div"); d.className = "comp"; d.innerHTML = `
${esc(c.name)} ${esc(c.ats)}
${esc(locs) || "location not listed"}
${c.n} open · top ${c.best.toFixed(2)} · view a posting
`; el.appendChild(d); } } $("#vJobs").onclick = () => setView("jobs"); $("#vCos").onclick = () => setView("cos"); function setView(v) { state.view = v; $("#vJobs").classList.toggle("on", v === "jobs"); $("#vCos").classList.toggle("on", v === "cos"); $("#jobs").style.display = v === "jobs" ? "" : "none"; $("#cos").style.display = v === "cos" ? "" : "none"; $("#more3").style.display = v === "jobs" ? "" : "none"; render(false); } $("#more3").onclick = () => render(false); $("#csv").onclick = () => { const q = (s) => `"${String(s ?? "").replace(/"/g, '""').replace(/\s+/g, " ").trim()}"`; const head = "match,title,employer,location,url,source,marked\n"; const body = ranked.map((j) => { const l = state.labels.get(key(j)); return [score(j).toFixed(4), q(j.title), q(co(j)), q(j.location), q(j.url), q(j.ats), l === 1 ? "keep" : l === 0 ? "drop" : ""].join(","); }).join("\n"); const blob = new Blob([head + body], { type: "text/csv;charset=utf-8" }); const a = document.createElement("a"); a.href = URL.createObjectURL(blob); a.download = `bos-market-scan-${new Date().toISOString().slice(0, 10)}.csv`; a.click(); URL.revokeObjectURL(a.href); }; document.addEventListener("keydown", (ev) => { if (!$("#s3").classList.contains("active") || state.view !== "jobs" || ev.target.tagName === "TEXTAREA" || ev.target.tagName === "INPUT") return; const j = ranked[cur]; if (!j) return; if (ev.key === "j" || ev.key === "J") { state.labels.set(key(j), 1); refit(); render(false); cur++; hi(); } else if (ev.key === "k" || ev.key === "K") { state.labels.set(key(j), 0); refit(); render(false); cur++; hi(); } else if (ev.key === " ") { ev.preventDefault(); cur++; hi(); } else if (ev.key === "ArrowUp") { cur = Math.max(0, cur - 1); hi(); } else if (ev.key === "ArrowDown") { cur++; hi(); } });