Staffing Intelligence Console: workforce command center with conversational AI

New page at /lakehouse/console — a $200/hr consultant's intelligence product:

Morning Brief (auto-loads in ~120ms across 500K profiles):
- Workforce Pulse: total, reliable %, elite %, archetype breakdown
- Geographic Bench: state-by-state reliable % with weakest-state alert
- Comeback Watch: 15K improving workers who crossed 80% reliability
- Risk Watch: 5K erratic + 5K silent workers flagged automatically
- Ready & Waiting: available + reliable workers to call first
- Role Supply: 20 roles with supply/available/reliability

Conversational Chat with 5 intelligent routes:
- "Find someone like [Name] but in OH" → vector similarity search
- "Who could handle industrial electrical work?" → semantic role discovery
  (finds workers for roles that DON'T EXIST in the database)
- "What if we lose our top 5 forklift operators?" → scenario analysis
  with risk rating, bench depth, state-by-state breakdown
- "Which workers should we stop placing?" → risk flagging
- Default: hybrid SQL+vector search with LLM summary

Every response shows: query steps, records scanned, response time.
Transparency kills the "AI is making it up" argument.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
root 2026-04-17 19:37:52 -05:00
parent 37c68d9567
commit 37804d7195
2 changed files with 512 additions and 1 deletions

380
mcp-server/console.html Normal file
View File

@ -0,0 +1,380 @@
<!DOCTYPE html>
<html><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Staffing Intelligence Console</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,system-ui,sans-serif;background:#06090f;color:#c9d1d9;font-size:14px;line-height:1.5}
.bar{background:#0d1117;padding:14px 20px;border-bottom:1px solid #1b2130;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px}
.bar h1{font-size:15px;font-weight:600;color:#f0f6fc;letter-spacing:0.5px}
.bar .rt{font-size:11px;color:#484f58}
.wrap{max-width:960px;margin:0 auto;padding:20px 16px}
.brief-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;margin-bottom:24px}
.bcard{background:#0d1117;border:1px solid #1b2130;border-radius:10px;padding:18px;position:relative;overflow:hidden}
.bcard .label{font-size:9px;text-transform:uppercase;letter-spacing:1.5px;color:#484f58;margin-bottom:8px}
.bcard .headline{font-size:16px;font-weight:700;color:#f0f6fc;margin-bottom:4px}
.bcard .sub{font-size:12px;color:#8b949e;margin-bottom:12px}
.bcard .big{font-size:36px;font-weight:800;line-height:1}
.bcard.pulse{border-left:3px solid #58a6ff}
.bcard.bench{border-left:3px solid #d29922}
.bcard.gems{border-left:3px solid #3fb950}
.bcard.risk{border-left:3px solid #f85149}
.bcard.talent{border-left:3px solid #bc8cff}
.bcard.supply{border-left:3px solid #79c0ff}
.arch-row{display:flex;gap:4px;flex-wrap:wrap;margin-top:10px}
.arch-pill{padding:3px 10px;border-radius:10px;font-size:11px;font-weight:500}
.bench-row{display:flex;align-items:center;gap:8px;margin-bottom:6px;font-size:12px}
.bench-row .st{width:24px;font-weight:600;color:#f0f6fc}
.bench-bar{flex:1;height:14px;background:#161b22;border-radius:4px;overflow:hidden;position:relative}
.bench-fill{height:100%;border-radius:4px;transition:width 0.8s}
.bench-row .pct{width:40px;text-align:right;font-size:11px;font-weight:600}
.wk{display:flex;align-items:center;gap:10px;padding:8px;background:#161b22;border-radius:6px;margin-bottom:4px}
.wk .av{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;color:#f0f6fc;flex-shrink:0}
.wk .info{flex:1;min-width:0}
.wk .nm{font-weight:600;color:#f0f6fc;font-size:13px}
.wk .det{color:#8b949e;font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wk .badge{padding:2px 8px;border-radius:8px;font-size:10px;font-weight:600;flex-shrink:0}
.prompts{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.prompt-btn{padding:8px 16px;background:#161b22;border:1px solid #1b2130;border-radius:20px;color:#8b949e;font-size:12px;cursor:pointer;transition:all 0.2s}
.prompt-btn:hover{border-color:#58a6ff;color:#58a6ff;background:#0d1525}
.chat-box{background:#0d1117;border:1px solid #1b2130;border-radius:12px;overflow:hidden;margin-bottom:16px}
.chat-messages{min-height:60px;max-height:600px;overflow-y:auto;padding:16px}
.msg{margin-bottom:16px;animation:fadeIn 0.3s ease}
@keyframes fadeIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.msg.user{text-align:right}
.msg.user .bubble{display:inline-block;background:#1f3d68;color:#c9d6ff;padding:10px 16px;border-radius:16px 16px 4px 16px;max-width:70%;text-align:left;font-size:13px}
.msg.system .bubble{background:#161b22;border:1px solid #1b2130;border-radius:4px 16px 16px 16px;padding:16px;font-size:13px}
.msg .meta{font-size:10px;color:#484f58;margin-top:6px}
.msg .steps{margin-bottom:10px}
.msg .step{font-size:11px;color:#58a6ff;padding:2px 0}
.msg .summary{font-size:14px;font-weight:600;color:#f0f6fc;margin-bottom:8px}
.msg .note{font-size:11px;color:#8b949e;font-style:italic;margin-top:8px;padding:8px;background:#0d1117;border-radius:6px}
.result-card{background:#0d1117;border:1px solid #1b2130;border-radius:8px;padding:12px;margin-bottom:6px}
.result-card .rc-name{font-weight:600;color:#f0f6fc;font-size:13px}
.result-card .rc-detail{font-size:11px;color:#8b949e;margin-top:2px}
.result-card .rc-score{font-size:10px;color:#58a6ff;margin-top:4px}
.result-card .rc-skills{display:flex;gap:4px;flex-wrap:wrap;margin-top:6px}
.result-card .rc-skill{padding:2px 8px;background:#1a2744;color:#58a6ff;border-radius:8px;font-size:10px}
.result-card .rc-cert{padding:2px 8px;background:#1a3a2a;color:#3fb950;border-radius:8px;font-size:10px}
.source-card{background:#1a1a00;border:1px solid #854d0e;border-radius:8px;padding:12px;margin-bottom:10px}
.whatif-severity{display:inline-block;padding:3px 10px;border-radius:8px;font-size:11px;font-weight:700;margin-left:8px}
.input-bar{display:flex;gap:8px;padding:12px 16px;border-top:1px solid #1b2130;background:#0d1117}
.input-bar input{flex:1;padding:12px 16px;background:#06090f;border:1px solid #1b2130;border-radius:10px;color:#f0f6fc;font-size:14px;outline:none}
.input-bar input:focus{border-color:#58a6ff}
.input-bar button{padding:12px 20px;background:#58a6ff;border:none;border-radius:10px;color:#0d1117;font-weight:700;font-size:14px;cursor:pointer}
.input-bar button:hover{background:#79c0ff}
.input-bar button:disabled{opacity:0.4;cursor:default}
.thinking{display:flex;align-items:center;gap:8px;color:#58a6ff;font-size:12px;padding:12px}
.dots span{animation:blink 1.4s infinite both;margin:0 1px}
.dots span:nth-child(2){animation-delay:0.2s}
.dots span:nth-child(3){animation-delay:0.4s}
@keyframes blink{0%,80%,100%{opacity:0.2}40%{opacity:1}}
.supply-row{display:flex;justify-content:space-between;align-items:center;padding:5px 8px;font-size:12px;border-bottom:1px solid #0d1117}
.supply-row:last-child{border-bottom:none}
.supply-role{color:#f0f6fc;font-weight:500}
.supply-nums{color:#8b949e;font-size:11px}
.ft{text-align:center;padding:16px;color:#2d333b;font-size:10px}
@media(max-width:768px){.brief-grid{grid-template-columns:1fr}.msg.user .bubble{max-width:90%}}
</style></head><body>
<div class="bar">
<h1>Staffing Intelligence Console</h1>
<div class="rt" id="brief-time">Analyzing 500,000 profiles...</div>
</div>
<div class="wrap">
<div id="brief" class="brief-grid"><div style="grid-column:1/-1;text-align:center;padding:40px;color:#484f58">Scanning your entire workforce...</div></div>
<div class="prompts" id="prompts"></div>
<div class="chat-box">
<div class="chat-messages" id="chat"></div>
<div class="input-bar">
<input type="text" id="q" placeholder="Ask anything about your workforce..." onkeydown="if(event.key==='Enter'&&!event.shiftKey)send()">
<button id="send-btn" onclick="send()">Send</button>
</div>
</div>
<div class="ft">Powered by Lakehouse — Hybrid SQL + Vector Search across 500,000 embedded worker profiles</div>
</div>
<script>
var P=location.pathname.replace(/\/console\/?$/,'');
var A=location.origin+P;
var AC=['#1a2744','#1a3a2a','#2a1a3a','#3a2a1a','#1a3a3a','#2a2a1a','#3a1a2a','#1a2a3a'];
var briefData=null;
function api(path,body){
return fetch(A+path,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body||{})}).then(function(r){return r.json()})
}
function el(tag,css,text){var e=document.createElement(tag);if(css)e.style.cssText=css;if(text)e.textContent=text;return e}
function div(cls,text){var d=document.createElement('div');if(cls)d.className=cls;if(text)d.textContent=text;return d}
window.addEventListener('load',loadBrief);
function loadBrief(){
api('/intelligence/brief').then(function(d){
briefData=d;
var container=document.getElementById('brief');
container.textContent='';
document.getElementById('brief-time').textContent='Analyzed '+(d.pool.total||0).toLocaleString()+' profiles in '+(d.duration_ms||0)+'ms';
var pool=d.pool;
var relPct=pool.total?Math.round(pool.reliable/pool.total*100):0;
var elitePct=pool.total?Math.round(pool.elite/pool.total*100):0;
// Card 1: Workforce Pulse
var c1=makeCard('pulse','WORKFORCE PULSE','Your A-Team',pool.reliable.toLocaleString()+' workers with 80%+ reliability — '+relPct+'% of your pool');
var bigRow=el('div','display:flex;gap:20px;margin-bottom:12px');
addBigNum(bigRow,pool.total.toLocaleString(),'Total Workers','#f0f6fc');
addBigNum(bigRow,relPct+'%','Reliable','#3fb950');
addBigNum(bigRow,elitePct+'%','Elite (90%+)','#58a6ff');
c1.appendChild(bigRow);
if(d.archetypes&&d.archetypes.length){
var ar=div('arch-row');
var archColors={reliable:'#3fb950',communicator:'#58a6ff',flexible:'#d29922',leader:'#bc8cff',specialist:'#f0883e',improving:'#79c0ff',erratic:'#f85149',silent:'#484f58'};
d.archetypes.forEach(function(a){
var pct=pool.total?Math.round(a.cnt/pool.total*100):0;
var color=archColors[a.archetype]||'#484f58';
var pill=el('span','background:'+color+'20;color:'+color+';border:1px solid '+color+'40;padding:3px 10px;border-radius:10px;font-size:11px;font-weight:500',a.archetype+' '+pct+'%');
pill.className='arch-pill';ar.appendChild(pill);
});
c1.appendChild(ar);
}
container.appendChild(c1);
// Card 2: Geographic Bench
var c2=makeCard('bench','GEOGRAPHIC BENCH','Where You\'re Strong — and Thin','Reliable worker density by state');
var sorted=(d.bench||[]).slice().sort(function(a,b){return (b.total?b.reliable/b.total:0)-(a.total?a.reliable/a.total:0)});
sorted.forEach(function(s){
var pct=s.total?Math.round(s.reliable/s.total*100):0;
var color=pct>45?'#3fb950':pct>35?'#d29922':'#f85149';
var row=div('bench-row');
row.appendChild(el('span','width:24px;font-weight:600;color:#f0f6fc',s.state));
var bar=el('div','flex:1;height:14px;background:#161b22;border-radius:4px;overflow:hidden');
bar.appendChild(el('div','height:100%;border-radius:4px;background:'+color+';width:'+pct+'%;transition:width 0.8s'));
row.appendChild(bar);
row.appendChild(el('span','width:40px;text-align:right;font-size:11px;font-weight:600;color:'+color,pct+'%'));
row.appendChild(el('span','font-size:10px;color:#484f58;width:60px',s.total.toLocaleString()));
c2.appendChild(row);
});
var weakest=sorted[sorted.length-1];
if(weakest){
var wpct=weakest.total?Math.round(weakest.reliable/weakest.total*100):0;
c2.appendChild(makeCallout('Warning: '+weakest.state+' is your thinnest bench at '+wpct+'% reliable. If a client there ramps up, you may struggle to fill.','#1a1500','#854d0e'));
}
container.appendChild(c2);
// Card 3: Comeback Watch
if(d.gems&&d.gems.length){
var c3=makeCard('gems','COMEBACK WATCH',pool.improving.toLocaleString()+' Workers Improving','These workers crossed 80% reliability — they earned a second look');
d.gems.forEach(function(w){
addWorkerMini(c3,w.name,w.role+' · '+w.city+', '+w.state,'Reliability: '+Math.round(w.rel*100)+'% rising','#79c0ff','improving');
});
c3.appendChild(makeCallout('These workers were previously below threshold. The system detected their improvement automatically — no staffer had to track it.','#0d261a','#238636'));
container.appendChild(c3);
}
// Card 4: Risk Watch
if(d.risks&&d.risks.length){
var c4=makeCard('risk','RISK WATCH',pool.erratic.toLocaleString()+' Erratic + '+pool.silent_cnt.toLocaleString()+' Silent Workers','Low reliability + behavioral flags — review placement priority');
d.risks.forEach(function(w){
addWorkerMini(c4,w.name,w.role+' · '+w.city+', '+w.state,'Reliability: '+Math.round(w.rel*100)+'% · Responsiveness: '+Math.round(w.resp*100)+'%','#f85149',w.archetype);
});
c4.appendChild(makeCallout('Not firing — deprioritizing. Every failed placement costs time and client trust. The system flags these automatically so you don\'t learn the hard way.','#2d0d0d','#7f1d1d'));
container.appendChild(c4);
}
// Card 5: Ready & Waiting
if(d.untapped&&d.untapped.length){
var c5=makeCard('talent','READY & WAITING','Available + Reliable — Call These First','85%+ reliability and actively available right now');
d.untapped.forEach(function(w){
addWorkerMini(c5,w.name,w.role+' · '+w.city+', '+w.state,'Available: '+Math.round(w.avail*100)+'% · Reliable: '+Math.round(w.rel*100)+'%','#bc8cff','ready');
});
container.appendChild(c5);
}
// Card 6: Role Supply
if(d.supply&&d.supply.length){
var c6=makeCard('supply','ROLE SUPPLY','Workers by Role','Roles with high supply but low availability may indicate scheduling problems');
d.supply.slice(0,10).forEach(function(r){
var row=div('supply-row');
row.appendChild(el('span','color:#f0f6fc;font-weight:500',r.role));
var nums=el('span','color:#8b949e;font-size:11px');
nums.appendChild(el('strong','color:#f0f6fc',r.supply.toLocaleString()));
nums.appendChild(document.createTextNode(' total · '));
nums.appendChild(el('strong','color:#f0f6fc',r.available.toLocaleString()));
nums.appendChild(document.createTextNode(' available · rel '+Math.round(r.avg_rel*100)+'%'));
row.appendChild(nums);c6.appendChild(row);
});
container.appendChild(c6);
}
setupPrompts(d);
}).catch(function(e){
document.getElementById('brief').textContent='Failed to load brief: '+e.message;
});
}
function makeCard(cls,label,headline,sub){
var d=div('bcard '+cls);
d.appendChild(div('label',label));d.appendChild(div('headline',headline));d.appendChild(div('sub',sub));return d;
}
function addBigNum(parent,num,label,color){
var d=el('div','');
var n=el('div','font-size:36px;font-weight:800;line-height:1;color:'+color,num);
d.appendChild(n);d.appendChild(el('div','font-size:10px;color:#484f58;margin-top:2px',label));parent.appendChild(d);
}
function addWorkerMini(parent,name,detail,extra,color,badge){
var w=div('wk');
var av=el('div','width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:12px;color:#f0f6fc;flex-shrink:0;background:'+AC[Math.floor(Math.random()*AC.length)]);
av.textContent=(name||'').split(' ').map(function(n){return(n[0]||'').toUpperCase()}).slice(0,2).join('');
var info=div('info');
info.appendChild(div('nm',name));info.appendChild(div('det',detail));
if(extra){var ex=div('det');ex.style.color='#58a6ff';ex.textContent=extra;info.appendChild(ex)}
w.appendChild(av);w.appendChild(info);
if(badge){var b=el('span','padding:2px 8px;border-radius:8px;font-size:10px;font-weight:600;background:'+(color||'#484f58')+'20;color:'+(color||'#484f58'),badge);w.appendChild(b)}
parent.appendChild(w);
}
function makeCallout(text,bg,border){
return el('div','font-size:11px;color:#8b949e;margin-top:8px;padding:8px 10px;background:'+(bg||'#0d1117')+';border:1px solid '+(border||'#1b2130')+';border-radius:6px;font-style:italic',text);
}
function setupPrompts(data){
var container=document.getElementById('prompts');container.textContent='';
var prompts=[];
if(data.gems&&data.gems[0])prompts.push('Find someone like '+data.gems[0].name+' but in OH');
prompts.push('Who could handle industrial electrical work?');
prompts.push('What if we lose our top 5 forklift operators?');
prompts.push('Which workers should we stop placing?');
if(data.supply&&data.supply.length>2){
var under=data.supply.slice().sort(function(a,b){return (a.available/a.supply)-(b.available/b.supply)})[0];
if(under)prompts.push('Show me available '+under.role+'s');
}
prompts.push('Find bilingual workers with leadership skills');
prompts.forEach(function(p){
var btn=el('button','',p);btn.className='prompt-btn';
btn.onclick=function(){document.getElementById('q').value=p;send()};
container.appendChild(btn);
});
}
// ─── Chat ───
function send(){
var input=document.getElementById('q');
var q=input.value.trim();if(!q)return;
input.value='';
var chat=document.getElementById('chat');
var userMsg=div('msg user');var bubble=div('bubble',q);userMsg.appendChild(bubble);chat.appendChild(userMsg);
var thinking=el('div','display:flex;align-items:center;gap:8px;color:#58a6ff;font-size:12px;padding:12px');
thinking.appendChild(document.createTextNode('Querying 500K profiles'));
var dots=el('span','');dots.className='dots';
dots.appendChild(el('span','','.'));dots.appendChild(el('span','','.'));dots.appendChild(el('span','','.'));
thinking.appendChild(dots);chat.appendChild(thinking);chat.scrollTop=chat.scrollHeight;
document.getElementById('send-btn').disabled=true;
api('/intelligence/chat',{message:q}).then(function(d){
thinking.remove();document.getElementById('send-btn').disabled=false;
var msg=div('msg system');var bbl=div('bubble');
// Steps
if(d.queries_run&&d.queries_run.length){
var steps=div('steps');
d.queries_run.forEach(function(s){steps.appendChild(el('div','font-size:11px;color:#58a6ff;padding:2px 0','→ '+s))});
bbl.appendChild(steps);
}
bbl.appendChild(div('summary',d.summary||''));
// Type-specific rendering
if(d.type==='similar'&&d.source){
var sc=div('source-card');
sc.appendChild(el('div','font-size:10px;color:#d29922;text-transform:uppercase;letter-spacing:1px;margin-bottom:4px','Source Worker'));
sc.appendChild(el('div','font-weight:700;color:#f0f6fc;font-size:14px',d.source.name));
sc.appendChild(el('div','font-size:12px;color:#d29922',d.source.role+' · '+d.source.city+', '+d.source.state+' · Reliability: '+Math.round(d.source.rel*100)+'%'));
sc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:4px','Skills: '+(d.source.skills||'none')+' · Archetype: '+(d.source.archetype||'unknown')));
bbl.appendChild(sc);
renderResults(bbl,d.results);
if(d.sql_matches)bbl.appendChild(el('div','font-size:10px;color:#484f58;margin-top:6px','Filtered pool: '+d.sql_matches.toLocaleString()+' workers'));
}
else if(d.type==='discovery'){
renderResults(bbl,d.results);
if(d.note)bbl.appendChild(el('div','font-size:11px;color:#8b949e;font-style:italic;margin-top:8px;padding:8px;background:#0d1117;border-radius:6px',d.note));
}
else if(d.type==='whatif'){
var sevColors={HIGH:['#7f1d1d','#fca5a5'],MEDIUM:['#854d0e','#fcd34d'],LOW:['#238636','#86efac']};
var sc2=sevColors[d.risk_level]||sevColors.MEDIUM;
var sev=el('span','display:inline-block;padding:3px 10px;border-radius:8px;font-size:11px;font-weight:700;margin-left:8px;background:'+sc2[0]+';color:'+sc2[1],'RISK: '+d.risk_level);
bbl.querySelector('.summary').appendChild(sev);
bbl.appendChild(el('div','font-size:11px;color:#f85149;margin:8px 0 4px;font-weight:600','Workers you\'d lose:'));
(d.lost||[]).forEach(function(w){
var rc=div('result-card');rc.style.borderLeft='3px solid #f85149';
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:13px',w.name));
rc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:2px',w.role+' · '+w.city+', '+w.state+' · Reliability: '+Math.round(w.rel*100)+'%'));
bbl.appendChild(rc);
});
bbl.appendChild(el('div','font-size:11px;color:#3fb950;margin:12px 0 4px;font-weight:600','Remaining bench: '+d.reliable_remaining+' reliable workers across '+(d.bench||[]).length+' states ('+d.total_in_role+' total in role)'));
(d.bench||[]).forEach(function(b){
var row=el('div','display:flex;justify-content:space-between;padding:4px 8px;font-size:12px');
row.appendChild(el('span','color:#f0f6fc',b.state+' — '+b.total+' total'));
row.appendChild(el('span','color:'+(b.reliable>5?'#3fb950':'#f85149'),b.reliable+' reliable'));
bbl.appendChild(row);
});
}
else if(d.type==='risk'){
(d.results||[]).forEach(function(w){
var rc=div('result-card');rc.style.borderLeft='3px solid #f85149';
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:13px',w.name));
rc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:2px',w.role+' · '+w.city+', '+w.state));
rc.appendChild(el('div','font-size:10px;color:#f85149;margin-top:4px','Reliability: '+Math.round(w.rel*100)+'% · Responsiveness: '+Math.round(w.resp*100)+'% · Compliance: '+Math.round(w.compl*100)+'% · '+w.archetype));
bbl.appendChild(rc);
});
if(d.total_flagged)bbl.appendChild(el('div','font-size:10px;color:#484f58;margin-top:6px',d.total_flagged.toLocaleString()+' total workers match this risk profile'));
}
else if(d.type==='search'||d.type==='answer'){
renderResults(bbl,d.results||d.sources||[]);
}
else if(d.type==='error'){
bbl.appendChild(el('div','color:#f85149;font-size:13px',d.summary));
}
if(d.duration_ms){
var meta=div('meta');
meta.appendChild(el('span','margin-right:12px',d.duration_ms+'ms'));
if(d.sql_matches)meta.appendChild(el('span','',d.sql_matches.toLocaleString()+' records scanned'));
bbl.appendChild(meta);
}
msg.appendChild(bbl);chat.appendChild(msg);chat.scrollTop=chat.scrollHeight;
}).catch(function(e){
thinking.remove();document.getElementById('send-btn').disabled=false;
var msg=div('msg system');var bbl=div('bubble');bbl.style.borderColor='#f85149';
bbl.appendChild(el('div','color:#f85149','Error: '+e.message));
msg.appendChild(bbl);chat.appendChild(msg);
});
}
function renderResults(parent,results){
if(!results||!results.length)return;
results.forEach(function(r){
var text=r.text||r.chunk_text||'';
var parts=text.split(/\u2014|\u2013|\u002D{2,}/);
var name=parts[0]?parts[0].trim():(r.name||r.doc_id||'Worker');
var rest=parts[1]?parts[1].trim():'';
var roleM=rest.match(/^(.+?)\s+in\s+(.+?)\./);
var skillM=rest.match(/Skills:\s*([^.]+)/);
var certM=rest.match(/Cert(?:s|ifications)?:\s*([^.]+)/);
var relM=rest.match(/Reliability:\s*([\d.]+)/);
var archM=rest.match(/Archetype:\s*(\w+)/);
var rc=div('result-card');
rc.appendChild(el('div','font-weight:600;color:#f0f6fc;font-size:13px',name));
if(roleM)rc.appendChild(el('div','font-size:11px;color:#8b949e;margin-top:2px',roleM[1]+' · '+roleM[2]));
var scoreParts=[];
if(r.score)scoreParts.push('Match: '+Math.round(r.score*100)+'%');
if(relM)scoreParts.push('Reliability: '+Math.round(relM[1]*100)+'%');
if(archM)scoreParts.push(archM[1]);
if(scoreParts.length)rc.appendChild(el('div','font-size:10px;color:#58a6ff;margin-top:4px',scoreParts.join(' · ')));
if(skillM||certM){
var tags=el('div','display:flex;gap:4px;flex-wrap:wrap;margin-top:6px');
if(skillM)skillM[1].split(/[|,]/).forEach(function(s){if(s.trim()){tags.appendChild(el('span','padding:2px 8px;background:#1a2744;color:#58a6ff;border-radius:8px;font-size:10px',s.trim()))}});
if(certM)certM[1].split(/[|,]/).forEach(function(c){if(c.trim()&&c.trim()!=='none'){tags.appendChild(el('span','padding:2px 8px;background:#1a3a2a;color:#3fb950;border-radius:8px;font-size:10px',c.trim()))}});
rc.appendChild(tags);
}
parent.appendChild(rc);
});
}
</script></body></html>

View File

@ -1029,8 +1029,139 @@ tr:hover{background:#111827}
return ok(await runWeekSimulation());
}
// ─── Staffing Intelligence Console ───
if (url.pathname === "/console") {
return new Response(Bun.file(import.meta.dir + "/console.html"));
}
// Intelligence Brief — parallel analytics across 500K profiles
if (url.pathname === "/intelligence/brief" && req.method === "POST") {
const start = Date.now();
const [poolR, benchR, supplyR, gemsR, risksR, untappedR, archetypeR] = await Promise.all([
api("POST", "/query/sql", { sql: `SELECT COUNT(*) total, ROUND(AVG(CAST(reliability AS DOUBLE)),3) avg_rel, SUM(CASE WHEN CAST(reliability AS DOUBLE)>0.9 THEN 1 ELSE 0 END) elite, SUM(CASE WHEN CAST(reliability AS DOUBLE)>0.8 THEN 1 ELSE 0 END) reliable, SUM(CASE WHEN archetype='erratic' THEN 1 ELSE 0 END) erratic, SUM(CASE WHEN archetype='silent' THEN 1 ELSE 0 END) silent_cnt, SUM(CASE WHEN archetype='improving' THEN 1 ELSE 0 END) improving FROM workers_500k` }),
api("POST", "/query/sql", { sql: `SELECT state, COUNT(*) total, ROUND(AVG(CAST(reliability AS DOUBLE)),3) avg_rel, SUM(CASE WHEN CAST(reliability AS DOUBLE)>0.8 THEN 1 ELSE 0 END) reliable, SUM(CASE WHEN CAST(availability AS DOUBLE)>0.5 THEN 1 ELSE 0 END) available FROM workers_500k GROUP BY state ORDER BY total DESC` }),
api("POST", "/query/sql", { sql: `SELECT role, COUNT(*) supply, SUM(CASE WHEN CAST(availability AS DOUBLE)>0.5 THEN 1 ELSE 0 END) available, ROUND(AVG(CAST(reliability AS DOUBLE)),3) avg_rel FROM workers_500k GROUP BY role ORDER BY supply DESC` }),
api("POST", "/query/sql", { sql: `SELECT name, role, city, state, ROUND(CAST(reliability AS DOUBLE),2) rel, ROUND(CAST(availability AS DOUBLE),2) avail, archetype, skills FROM workers_500k WHERE archetype='improving' AND CAST(reliability AS DOUBLE)>0.8 ORDER BY CAST(reliability AS DOUBLE) DESC LIMIT 5` }),
api("POST", "/query/sql", { sql: `SELECT name, role, city, state, ROUND(CAST(reliability AS DOUBLE),2) rel, ROUND(CAST(responsiveness AS DOUBLE),2) resp, ROUND(CAST(compliance AS DOUBLE),2) compl, archetype FROM workers_500k WHERE archetype IN ('erratic','silent') AND CAST(reliability AS DOUBLE)<0.5 ORDER BY CAST(reliability AS DOUBLE) ASC LIMIT 5` }),
api("POST", "/query/sql", { sql: `SELECT name, role, city, state, ROUND(CAST(availability AS DOUBLE),2) avail, ROUND(CAST(reliability AS DOUBLE),2) rel, skills, archetype FROM workers_500k WHERE CAST(availability AS DOUBLE)>0.8 AND CAST(reliability AS DOUBLE)>0.85 ORDER BY CAST(availability AS DOUBLE) DESC LIMIT 5` }),
api("POST", "/query/sql", { sql: `SELECT archetype, COUNT(*) cnt, ROUND(AVG(CAST(reliability AS DOUBLE)),3) avg_rel FROM workers_500k GROUP BY archetype ORDER BY cnt DESC` }),
]);
return ok({
pool: poolR.rows?.[0] || {},
bench: benchR.rows || [],
supply: supplyR.rows || [],
gems: gemsR.rows || [],
risks: risksR.rows || [],
untapped: untappedR.rows || [],
archetypes: archetypeR.rows || [],
duration_ms: Date.now() - start,
});
}
// Intelligence Chat — natural language → routed queries → structured results
if (url.pathname === "/intelligence/chat" && req.method === "POST") {
const b = await json();
const q = (b.message || "").trim();
const lower = q.toLowerCase();
const start = Date.now();
const queries: string[] = [];
// Route 1: "Find someone like [Name]"
const likeMatch = q.match(/(?:like|similar to)\s+([A-Z][a-z]+(?:\s+[A-Z]\.?\s*)?(?:[A-Z][a-z]+)?)/i);
if (likeMatch) {
const name = likeMatch[1].trim();
queries.push(`SQL: Looking up ${name}'s profile`);
const profileR = await api("POST", "/query/sql", { sql: `SELECT * FROM workers_500k WHERE name LIKE '%${name.replace(/'/g,"''")}%' LIMIT 1` });
if (profileR.rows?.length) {
const worker = profileR.rows[0];
const stateMatch = lower.match(/\b(?:in|from)\s+([A-Z]{2})\b/i) || lower.match(/\b(IL|IN|OH|MO|TN|KY|WI|MI|IA|MN)\b/i);
const stateFilter = stateMatch ? `state = '${stateMatch[1].toUpperCase()}'` : `state != '${worker.state}'`;
queries.push(`Vector: Semantic similarity on ${worker.name}'s full profile → ${stateFilter}`);
const searchR = await api("POST", "/vectors/hybrid", {
question: worker.resume_text || `${worker.role} in ${worker.city} with skills ${worker.skills}`,
index_name: "workers_500k_v1",
sql_filter: stateFilter + ` AND CAST(reliability AS DOUBLE) >= 0.7`,
filter_dataset: "ethereal_workers", id_column: "worker_id", top_k: 5, generate: false,
});
return ok({ type: "similar", summary: `Found ${(searchR.sources||[]).length} workers similar to ${worker.name}${stateMatch ? ' in '+stateMatch[1].toUpperCase() : ' (other states)'}`,
source: { name: worker.name, role: worker.role, city: worker.city, state: worker.state, rel: worker.reliability, skills: worker.skills, archetype: worker.archetype },
results: (searchR.sources||[]).map((s:any) => ({ doc_id: s.doc_id, score: s.score, text: s.chunk_text })),
sql_matches: searchR.sql_matches, queries_run: queries, duration_ms: Date.now() - start });
}
return ok({ type: "error", summary: `Couldn't find "${name}" in the database. Try a full name.`, queries_run: queries, duration_ms: Date.now() - start });
}
// Route 2: "What if we lose"
if (/what if|lose|happens if/i.test(lower)) {
const roleMatch = lower.match(/(?:lose|lost?)\s+(?:our\s+)?(?:top\s+)?(\d+)?\s*(.+?)(?:\?|$)/i);
if (roleMatch) {
const count = parseInt(roleMatch[1]) || 5;
const subject = roleMatch[2].trim().replace(/\s*workers?\s*$/,'').replace(/s$/,'');
queries.push(`SQL: Top ${count} ${subject}s by reliability`);
const topR = await api("POST", "/query/sql", { sql: `SELECT name, role, city, state, ROUND(CAST(reliability AS DOUBLE),2) rel, skills FROM workers_500k WHERE LOWER(role) LIKE '%${subject.replace(/'/g,"''")}%' ORDER BY CAST(reliability AS DOUBLE) DESC LIMIT ${count}` });
if (topR.rows?.length) {
const states = [...new Set(topR.rows.map((r:any) => r.state))];
queries.push(`SQL: Bench depth for ${subject}s in ${states.join(', ')}`);
const benchR = await api("POST", "/query/sql", { sql: `SELECT state, COUNT(*) total, SUM(CASE WHEN CAST(reliability AS DOUBLE)>0.8 THEN 1 ELSE 0 END) reliable FROM workers_500k WHERE LOWER(role) LIKE '%${subject.replace(/'/g,"''")}%' AND state IN (${states.map((s:string)=>`'${s}'`).join(',')}) GROUP BY state` });
const totalInRole = (benchR.rows||[]).reduce((s:number,r:any) => s + r.total, 0);
const reliableRemaining = (benchR.rows||[]).reduce((s:number,r:any) => s + r.reliable, 0) - topR.rows.length;
return ok({ type: "whatif", summary: `Impact: losing top ${topR.rows.length} ${subject} workers`,
lost: topR.rows, bench: benchR.rows||[], total_in_role: totalInRole, reliable_remaining: Math.max(0, reliableRemaining),
risk_level: reliableRemaining < count * 2 ? "HIGH" : reliableRemaining < count * 5 ? "MEDIUM" : "LOW",
queries_run: queries, duration_ms: Date.now() - start });
}
return ok({ type: "error", summary: `Couldn't find workers in the "${subject}" role. Try: welder, forklift operator, assembler, etc.`, queries_run: queries, duration_ms: Date.now() - start });
}
}
// Route 3: "Who could handle" — semantic role discovery
if (/could handle|capable of|suitable for|qualified for|try.*for|can do/i.test(lower)) {
const roleDesc = q.replace(/^.*?(?:handle|capable of|suitable for|qualified for|try\s+\w+\s+for|can do)\s*/i,'').replace(/\?$/,'').trim();
queries.push(`Vector: Semantic search for "${roleDesc}" — no exact role match needed`);
const searchR = await api("POST", "/vectors/hybrid", {
question: `Worker experienced in ${roleDesc}, relevant skills and certifications`,
index_name: "workers_500k_v1", sql_filter: "CAST(reliability AS DOUBLE) >= 0.75",
filter_dataset: "ethereal_workers", id_column: "worker_id", top_k: 8, generate: false,
});
return ok({ type: "discovery", summary: `${(searchR.sources||[]).length} workers found through semantic skill matching for: "${roleDesc}"`,
role_searched: roleDesc, results: (searchR.sources||[]).map((s:any) => ({ doc_id: s.doc_id, score: s.score, text: s.chunk_text })),
sql_matches: searchR.sql_matches,
note: "None of these workers have this exact role title. They were found because their skills, certifications, and experience are semantically similar. This is talent discovery — finding people for roles that don't exist in your database yet.",
queries_run: queries, duration_ms: Date.now() - start });
}
// Route 4: "Stop placing" / risk workers
if (/stop placing|worst|problem|flag|risk|underperform|fire|let go/i.test(lower)) {
queries.push("SQL: erratic/silent workers with reliability < 50%");
const riskR = await api("POST", "/query/sql", { sql: `SELECT name, role, city, state, ROUND(CAST(reliability AS DOUBLE),2) rel, ROUND(CAST(responsiveness AS DOUBLE),2) resp, ROUND(CAST(compliance AS DOUBLE),2) compl, archetype FROM workers_500k WHERE archetype IN ('erratic','silent') AND CAST(reliability AS DOUBLE)<0.5 ORDER BY CAST(reliability AS DOUBLE) ASC LIMIT 10` });
const countR = await api("POST", "/query/sql", { sql: `SELECT COUNT(*) cnt FROM workers_500k WHERE archetype IN ('erratic','silent') AND CAST(reliability AS DOUBLE)<0.5` });
return ok({ type: "risk", summary: `${countR.rows?.[0]?.cnt || 0} workers flagged — showing the 10 lowest performers`,
results: riskR.rows||[], total_flagged: countR.rows?.[0]?.cnt || 0,
queries_run: queries, duration_ms: Date.now() - start });
}
// Route 5: Analytics / counts
if (/how many|count|total|percentage|average|breakdown/i.test(lower)) {
queries.push("RAG: analytical question → vector retrieval + LLM reasoning");
const ragR = await api("POST", "/vectors/rag", { index_name: "workers_500k_v1", question: q, top_k: 3 });
return ok({ type: "answer", summary: ragR.answer || "Couldn't determine the answer from the data",
sources: (ragR.sources||[]).map((s:any) => ({ doc_id: s.doc_id, text: s.chunk_text, score: s.score })),
queries_run: queries, duration_ms: Date.now() - start });
}
// Default: hybrid search with generation
queries.push("Hybrid: SQL filter + vector semantic search + LLM summary");
const searchR = await api("POST", "/vectors/hybrid", {
question: q, index_name: "workers_500k_v1", sql_filter: "CAST(reliability AS DOUBLE) >= 0.5",
filter_dataset: "ethereal_workers", id_column: "worker_id", top_k: 5, generate: true,
});
return ok({ type: "search", summary: searchR.answer || `Found ${(searchR.sources||[]).length} matching workers`,
results: (searchR.sources||[]).map((s:any) => ({ doc_id: s.doc_id, score: s.score, text: s.chunk_text })),
sql_matches: searchR.sql_matches, queries_run: queries, duration_ms: Date.now() - start });
}
activeTrace = null;
return err("Unknown path. Available: / /health /search /sql /match /worker/:id /ask /log /playbooks /profile/:id /vram /context /verify /simulation/run", 404);
return err("Unknown path. Available: / /health /search /sql /match /worker/:id /ask /log /playbooks /profile/:id /vram /context /verify /simulation/run /console /intelligence/brief /intelligence/chat", 404);
} catch (e: any) {
if (activeTrace) { scoreTrace(activeTrace, "error", 0, e.message); }
activeTrace = null;