diff --git a/mcp-server/search.html b/mcp-server/search.html
index 9c4bcb6..9517d28 100644
--- a/mcp-server/search.html
+++ b/mcp-server/search.html
@@ -619,11 +619,51 @@ function showProfile(workerData){
body.appendChild(srcBox);
}
+ // Past playbook history — Phase 19 institutional memory surfaced on
+ // the worker's own profile. Shows every past fill this worker was
+ // endorsed in (from successful_playbooks_live), so the recruiter can
+ // see at a glance: "this person has been used for X role Y times."
+ addSection(body,'Past Playbooks','Where this worker has been endorsed before');
+ var histBox=document.createElement('div');histBox.id='hist-'+(workerData.nm||'anon').replace(/\s/g,'-');
+ histBox.style.cssText='background:#0d1117;border-radius:8px;padding:14px;margin-bottom:20px;font-size:12px;color:#8b949e;line-height:1.6';
+ histBox.textContent='Loading history...';body.appendChild(histBox);
+ var city=(workerData.loc||'').split(',')[0].trim();
+ var state=(workerData.loc||'').split(',').pop().trim();
+ var nameLit=(workerData.nm||'').replace(/'/g,"''");
+ var sqlQ="SELECT operation, approach, context, timestamp FROM successful_playbooks_live "
+ +"WHERE result LIKE '%"+nameLit+"%' ORDER BY timestamp DESC LIMIT 8";
+ api('/sql',{sql:sqlQ}).then(function(r){
+ histBox.textContent='';
+ var rows=(r&&r.rows)||[];
+ if(rows.length===0){
+ histBox.textContent='No prior playbooks for '+(workerData.nm||'this worker')+' yet. First placement builds the first entry.';
+ histBox.style.color='#484f58';return;
+ }
+ var hdr2=document.createElement('div');hdr2.style.cssText='color:#3fb950;font-weight:600;margin-bottom:8px;font-size:11px';
+ hdr2.textContent=rows.length+' past endorsement'+(rows.length!==1?'s':'');
+ histBox.appendChild(hdr2);
+ rows.forEach(function(pb){
+ var row=document.createElement('div');row.style.cssText='padding:6px 10px;background:#161b22;border-radius:6px;margin-bottom:4px;border-left:2px solid #2ea043';
+ var op=document.createElement('div');op.style.cssText='color:#e6edf3;font-weight:500;font-size:12px';
+ op.textContent=pb.operation||'(unknown op)';row.appendChild(op);
+ var meta=document.createElement('div');meta.style.cssText='color:#8b949e;font-size:10px;margin-top:2px';
+ var ts=(pb.timestamp||'').substring(0,10);
+ meta.textContent=ts+' · '+(pb.approach||'').slice(0,40)+(pb.context?' · '+pb.context.slice(0,30):'');
+ row.appendChild(meta);histBox.appendChild(row);
+ });
+ }).catch(function(){
+ histBox.textContent='(history unavailable)';histBox.style.color='#484f58';
+ });
+
// Actions
var acts=document.createElement('div');acts.style.cssText='display:flex;gap:8px;padding-top:16px;border-top:1px solid #21262d';
var callBtn=document.createElement('button');callBtn.style.cssText='flex:1;padding:12px;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;border:none;background:#1f3d68;color:#58a6ff';callBtn.textContent='Call';
+ callBtn.onclick=function(){logAction(workerData,'call',callBtn)};
var smsBtn=document.createElement('button');smsBtn.style.cssText='flex:1;padding:12px;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;border:none;background:#0d261a;color:#3fb950';smsBtn.textContent='Send SMS';
- acts.appendChild(callBtn);acts.appendChild(smsBtn);body.appendChild(acts);
+ smsBtn.onclick=function(){logAction(workerData,'sms',smsBtn)};
+ var noshowBtn=document.createElement('button');noshowBtn.style.cssText='flex:1;padding:12px;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;border:none;background:#3a1a1a;color:#f85149';noshowBtn.textContent='No-show';
+ noshowBtn.onclick=function(){logAction(workerData,'failure',noshowBtn)};
+ acts.appendChild(callBtn);acts.appendChild(smsBtn);acts.appendChild(noshowBtn);body.appendChild(acts);
modal.appendChild(body);overlay.appendChild(modal);document.body.appendChild(overlay);
}