diff --git a/mcp-server/index.ts b/mcp-server/index.ts index c9c940f..5964745 100644 --- a/mcp-server/index.ts +++ b/mcp-server/index.ts @@ -1240,6 +1240,107 @@ tr:hover{background:#111827} } } + // Intelligence: Chicago permits → assumed staffing contracts with + // Phase 19-ranked candidates and Path-2 discovered patterns. Each + // card pairs a REAL permit (live from data.cityofchicago.org) with + // a PROPOSED fill drawn from our 500K worker bench. Surfaces the + // meta-index dimension directly: "what past similar fills had in + // common" for this role + geo. + if (url.pathname === "/intelligence/permit_contracts" && req.method === "POST") { + const start = Date.now(); + try { + const permitUrl = "https://data.cityofchicago.org/resource/ydr8-5enu.json"; + // Recent + substantial permits only — skip tiny ones that + // don't imply real staffing demand. + const permits: any[] = await fetch( + `${permitUrl}?$select=permit_type,work_type,work_description,reported_cost,street_number,street_direction,street_name,community_area,issue_date&` + + `$where=reported_cost>250000 AND issue_date>'2025-06-01'` + + `&$order=issue_date DESC&$limit=6` + ).then(r => r.json()).catch(() => []); + + const typeToRole: Record = { + "Electrical Work": "Electrician", + "Masonry Work": "Production Worker", + "Mechanical Work": "Maintenance Tech", + "Reroofing": "Production Worker", + "Plumbing Work": "Maintenance Tech", + }; + + const contracts: any[] = []; + for (const p of permits) { + const cost = parseFloat(p.reported_cost || 0); + // Industry heuristic — one worker per $150K of permit value, + // capped at 8 per contract for staffing realism. + const count = Math.min(Math.max(Math.round(cost / 150000), 2), 8); + const role = typeToRole[p.work_type || ""] || "Production Worker"; + const city = "Chicago"; + const state = "IL"; + + // Phase 19 ranked candidates. Soft availability filter + // auto-applied by /search — this mirrors the real recruiter + // query path exactly. + const searchRes = await api("POST", "/vectors/hybrid", { + index_name: "workers_500k_v1", + filter_dataset: "workers_500k", + id_column: "worker_id", + sql_filter: `role = '${role}' AND state = '${state}' AND city = '${city}' AND CAST(availability AS DOUBLE) > 0.5`, + question: `${role} for ${p.work_type || "construction"} in ${city}`, + top_k: 5, generate: false, + use_playbook_memory: true, playbook_memory_k: 25, + }).catch(() => ({ sources: [] as any[] })); + + // Path 2 — discovered patterns for this role in this city. + const patternRes = await api("POST", "/vectors/playbook_memory/patterns", { + query: `${role} in ${city}, ${state}`, + top_k_playbooks: 25, + min_trait_frequency: 0.3, + }).catch(() => ({} as any)); + + const sources = (searchRes.sources || []).slice(0, 5).map((s: any) => { + const name = String(s.chunk_text || "").split("—")[0]?.trim() || s.doc_id; + return { + doc_id: s.doc_id, + name, + score: s.score, + playbook_boost: s.playbook_boost || 0, + playbook_citations: s.playbook_citations || [], + }; + }); + + contracts.push({ + permit: { + cost, + work_type: p.work_type || "General construction", + description: (p.work_description || "").substring(0, 140), + address: `${p.street_number || ""} ${p.street_direction || ""} ${p.street_name || ""}`.trim(), + community_area: p.community_area, + issue_date: (p.issue_date || "").substring(0, 10), + }, + proposed: { + role, + count, + city, state, + pool_size: searchRes.sql_matches, + candidates: sources, + }, + discovered_pattern: patternRes.discovered_pattern, + pattern_matched: patternRes.matched_playbooks ?? 0, + pattern_workers_examined: patternRes.total_workers_examined ?? 0, + }); + } + + return ok({ + generated_at: new Date().toISOString(), + count: contracts.length, + contracts, + duration_ms: Date.now() - start, + note: "Live Chicago permits paired with workers_500k-ranked candidates and playbook_memory discovered patterns. The permit is real public data; the proposed fill is derived per industry heuristic (~$150K → 1 worker).", + }); + } catch (e: any) { + return err(`permit_contracts: ${e.message}`, 500); + } + } + // Intelligence: Log a search → selection as a learned pattern if (url.pathname === "/intelligence/learn" && req.method === "POST") { const b = await json(); diff --git a/mcp-server/search.html b/mcp-server/search.html index c502423..e91fefd 100644 --- a/mcp-server/search.html +++ b/mcp-server/search.html @@ -112,6 +112,14 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
Analyzing contracts and workers...
+
+
+ Live Contracts — Chicago Permits → Proposed Fills + +
+
Loading live contracts...
+
+
Market Intelligence @@ -147,12 +155,84 @@ var P=location.pathname.indexOf('/lakehouse')>=0?'/lakehouse':''; var A=location.origin+P; var AC=['#1a2744','#1a3a2a','#2a1a3a','#3a2a1a','#1a3a3a','#2a2a1a']; var lastQuery=''; -window.addEventListener('load',function(){loadDay();loadMarket();loadLearning()}); +window.addEventListener('load',function(){loadDay();loadLiveContracts();loadMarket();loadLearning()}); 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 loadLiveContracts(){ + // Pair live Chicago permits with our 500K worker bench and the + // meta-index discovered patterns for each role+geo. This is the + // "real external data meets synthetic playbook learning" card set. + api('/intelligence/permit_contracts',{}).then(function(r){ + var el=document.getElementById('live-contracts');el.textContent=''; + if(!r||!r.contracts||r.contracts.length===0){ + el.textContent='No permits returned.';return; + } + r.contracts.forEach(function(c){ + var p=c.permit||{}, prop=c.proposed||{}; + var card=document.createElement('div');card.className='insight info'; + card.style.cssText='background:#0d1117;border:1px solid #171d27;border-radius:10px;padding:16px;margin-bottom:10px;border-left:3px solid #388bfd'; + // Header — permit + var hdr=document.createElement('div');hdr.style.cssText='display:flex;justify-content:space-between;margin-bottom:8px;gap:12px'; + var left=document.createElement('div'); + var title=document.createElement('div');title.style.cssText='font-weight:600;color:#e6edf3;font-size:14px'; + title.textContent='$'+(p.cost||0).toLocaleString()+' · '+(p.work_type||''); + var addr=document.createElement('div');addr.style.cssText='color:#8b949e;font-size:12px;margin-top:2px'; + addr.textContent=(p.address||'')+' · Chicago, IL · '+(p.issue_date||''); + left.appendChild(title);left.appendChild(addr); + var right=document.createElement('div');right.style.cssText='color:#58a6ff;font-size:12px;font-weight:600;text-align:right;white-space:nowrap'; + right.textContent=prop.count+'× '+prop.role; + var sub=document.createElement('div');sub.style.cssText='color:#545d68;font-size:10px;text-align:right'; + sub.textContent='pool: '+(prop.pool_size||'?').toLocaleString()+' available'; + right.appendChild(sub); + hdr.appendChild(left);hdr.appendChild(right);card.appendChild(hdr); + // Description + if(p.description){ + var desc=document.createElement('div');desc.style.cssText='color:#94a3b8;font-size:11px;margin-bottom:10px;line-height:1.5'; + desc.textContent=p.description;card.appendChild(desc); + } + // Pattern (meta-index) chip + if(c.discovered_pattern){ + var pat=document.createElement('div');pat.style.cssText='background:#0d2818;border:1px solid #2ea04360;border-radius:6px;padding:8px 12px;margin-bottom:10px;font-size:11px;color:#86efac;line-height:1.5'; + var plabel=document.createElement('span');plabel.style.cssText='color:#3fb950;font-weight:600;margin-right:6px'; + plabel.textContent='MEMORY ('+c.pattern_matched+' playbooks):'; + pat.appendChild(plabel); + pat.appendChild(document.createTextNode(' '+c.discovered_pattern)); + card.appendChild(pat); + } + // Candidates + var cands=prop.candidates||[]; + cands.slice(0,3).forEach(function(cand,i){ + var row=document.createElement('div');row.style.cssText='display:flex;align-items:center;gap:10px;padding:6px 10px;background:#161b22;border-radius:6px;margin-bottom:4px;font-size:12px'; + var av=document.createElement('div');av.style.cssText='width:28px;height:28px;border-radius:6px;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:10px;color:#e6edf3;background:'+AC[i%AC.length]; + av.textContent=(cand.name||'?').split(' ').map(function(n){return (n[0]||'').toUpperCase()}).join('').substring(0,2); + var info=document.createElement('div');info.style.cssText='flex:1;min-width:0'; + var nm=document.createElement('div');nm.style.cssText='color:#e6edf3;font-weight:500';nm.textContent=cand.name||cand.doc_id; + if((cand.playbook_boost||0)>0){ + var chip=document.createElement('span');chip.style.cssText='margin-left:8px;padding:2px 7px;border-radius:9px;font-size:9px;font-weight:600;background:#0d2818;border:1px solid #2ea043;color:#3fb950;vertical-align:middle'; + chip.textContent='Endorsed · '+(cand.playbook_citations||[]).length+' playbook'+((cand.playbook_citations||[]).length===1?'':'s'); + nm.appendChild(chip); + } + var sub2=document.createElement('div');sub2.style.cssText='color:#545d68;font-size:10px'; + sub2.textContent=cand.doc_id+' · score '+(cand.score||0).toFixed(3); + info.appendChild(nm);info.appendChild(sub2); + row.appendChild(av);row.appendChild(info); + card.appendChild(row); + }); + if(cands.length>3){ + var more=document.createElement('div');more.style.cssText='font-size:10px;color:#58a6ff;padding:4px 10px;margin-top:2px'; + more.textContent='+ '+(cands.length-3)+' more candidates available'; + card.appendChild(more); + } + el.appendChild(card); + }); + }).catch(function(e){ + document.getElementById('live-contracts').textContent='Error loading: '+e.message; + }); +} + function loadDay(){ // Step 1: run simulation + get real worker count + populate dropdowns from actual data Promise.all([