ui: staffing co-pilot UX fixes — new-tab reference nav + discoverable collapsibles
Reconciles month-old working-tree UX work (served per-request, live on the demo since 2026-05-30) into git. Implements UX_FIX_PLAN.md's 5 user complaints: reference pages (Profiler/Architecture/Spec/Onboard/Alerts/Workspaces) open in new tabs; contract-card collapsible shows a persistent chevron + expand/collapse label in both states; proof.html gains a substrate-signals chapter. Not authored this session — captured as-is (working state verified: pages serve 200). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7dddb98f4b
commit
7365a4c23e
94
mcp-server/UX_FIX_PLAN.md
Normal file
94
mcp-server/UX_FIX_PLAN.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# Staffing Co-Pilot UX Fix Plan (devop.live/lakehouse)
|
||||||
|
|
||||||
|
**Target file:** `/home/profit/lakehouse/mcp-server/search.html` (239KB, ~4100 lines) — THIS is the
|
||||||
|
main dashboard served at `/` (route at `index.ts:1258`; name "search.html" is historical).
|
||||||
|
Sibling pages: `console.html` (Walkthrough), `proof.html` (Architecture), `spec.html`, `onboard.html`,
|
||||||
|
`profiler.html`, `contractor.html`, `workspaces.html`, `alerts.html`.
|
||||||
|
|
||||||
|
**Serving:** Bun `mcp-server/index.ts` on `:3700`, nginx `/lakehouse/` → `127.0.0.1:3700`.
|
||||||
|
Restart after edits: HTML is read per-request (`Bun.file`), so **no restart needed for .html edits** —
|
||||||
|
just reload the browser. (Restart only if editing index.ts: it's pid 1254, `bun run mcp-server/index.ts`.)
|
||||||
|
|
||||||
|
**Constraints:** neo-brutalist, compact, distinct colors, NO fake timers. Surgical edits only.
|
||||||
|
Dashboard fires real SQL + /intelligence/* — don't break data wiring. Repo is FROZEN Rust legacy;
|
||||||
|
J explicitly authorized work on this surface.
|
||||||
|
|
||||||
|
**Base path quirk:** nav uses `var P = location.pathname.indexOf('/lakehouse')>=0?'/lakehouse':''`.
|
||||||
|
Relative hrefs (`href="console"`) resolve fine under `/lakehouse/`.
|
||||||
|
|
||||||
|
## User's 5 complaints → fixes (line numbers in search.html)
|
||||||
|
|
||||||
|
### 1+2. New tabs for reference pages (HIGH)
|
||||||
|
- **Top nav lines 594-599**: add `target="_blank" rel="noopener"` to Profiler, Architecture(proof),
|
||||||
|
Spec, Onboard, Alerts, Workspaces. LEAVE 592-593 (Dashboard `href="."`, Walkthrough `href="console"`) same-tab.
|
||||||
|
- **Footer line 781**: `<a href="proof">Architecture</a>` → add `target="_blank" rel="noopener"`. Keep Console same-tab.
|
||||||
|
- **Dynamic footer lines 1024-1026**: proof link needs `target=_blank rel=noopener` + `.ft` class styling (currently unstyled).
|
||||||
|
|
||||||
|
### 3. Collapsible "preview" not discoverable (HIGH)
|
||||||
|
Primary = **contract card expandable panel** (markup ~2620-2820, CSS grid-template-rows ~160-220).
|
||||||
|
Chevron rotates 180° but hint text "click for full curve…" only shows collapsed; vanishes on expand.
|
||||||
|
Fix: chevron always visible+larger(16px); persistent "Expand details"/"Collapse" label in BOTH states;
|
||||||
|
cursor:pointer on card header; hover border-left/bg shift; optional localStorage per-card.
|
||||||
|
Secondary collapsibles: ⓪ legacy-bridge narrative (~820-900) → default COLLAPSED for returning users
|
||||||
|
(localStorage 'seen_intro'); ② Staffer's Console preview (~1400-1500) → make collapsible, "Open full console →".
|
||||||
|
|
||||||
|
### 4. Clickable elements don't look clickable (HIGH)
|
||||||
|
Add global CSS: `[onclick]{cursor:pointer}` + reusable `.clickable` class with :hover (bg lift #161b22→#1c2333
|
||||||
|
+ border accent), :active (translateY(1px)), :focus-visible (outline).
|
||||||
|
Apply to: insight cards (~1180-1280), alert rows (~1700-1780), worker result rows (~990-1030 — add hover '›' chevron
|
||||||
|
for drilldown discoverability per feedback_test_drilldowns), collapsible section headers (~820-830, ~1400-1410),
|
||||||
|
action chips/buttons (~740-760, standardize .btn/.chip).
|
||||||
|
|
||||||
|
### 5. Layout clutter / flat hierarchy (HIGH)
|
||||||
|
8 sections at equal weight: ⓪ Not-a-CRM narrative, ① Live Market, Forecast, ② Staffer Console,
|
||||||
|
Market Intelligence, ③ Worker Search, ④ System Activity, ⑤ Substrate Signals.
|
||||||
|
3-tier fix: PRIMARY always-visible (Live Market, Worker Search, Staffer Console);
|
||||||
|
SECONDARY collapsible-open (Forecast, Market Intelligence); TERTIARY collapse-by-default or relocate
|
||||||
|
(⓪ narrative → collapsible banner; ⑤ Substrate Signals → move to proof.html/Architecture; ④ System Activity demote).
|
||||||
|
Also: Live Market vs Market Intelligence may overlap — differentiate headers or merge w/ sub-tabs.
|
||||||
|
Long card walls → add "show top 5 / show all" truncation.
|
||||||
|
|
||||||
|
### Cross-page nav consistency (MEDIUM)
|
||||||
|
Each of 8 pages has hardcoded nav with differing link sets/order/labels and unreliable .active.
|
||||||
|
Canonical set + order, each page sets .active on its own entry, brand/logo → `href="."`.
|
||||||
|
Long-term: extract nav to shared JS snippet served by index.ts to stop drift.
|
||||||
|
|
||||||
|
## ✅ SHIPPED 2026-05-30 (live-verified via curl against :3700; HTML served per-request → no restart)
|
||||||
|
- **#1+#2 New tabs** — search.html: 6 nav reference links (Profiler/Architecture/Spec/Onboard/Alerts/Workspaces)
|
||||||
|
+ footer Architecture + dynamic-footer Architecture now `target="_blank" rel="noopener"` with ↗ glyph.
|
||||||
|
Dashboard + Walkthrough stay same-tab (primary flow). VERIFIED: 7 static new-tab links served; nav listing clean.
|
||||||
|
- **#4 Clickability** — global affordance CSS inserted after `.ft a:hover{...}` (NOT `.ft a{margin}` — that anchor
|
||||||
|
was a hallucination): `[onclick]{cursor:pointer}`, `[role=button]`, `.iworker` cursor+hover-lift+active,
|
||||||
|
`details>summary` cursor+hover, global `:focus-visible`. VERIFIED served (affordance_css=1, iworker_cursor=1, summary_hover=1).
|
||||||
|
- **#3 partial** — every `<details>` collapsible now has visible hover affordance (cursor+bg). Contract-card toggle NOT yet (below).
|
||||||
|
- **Nav consistency** — added Profiler link to onboard/workspaces/alerts (verified profiler=1 each);
|
||||||
|
fixed contractor.html back-link `href="/"`→`href="."` (real bug: `/` = LLM-Team UI on :5000, ejected users out of lakehouse; verified root-bug=0, dot-fixed=1);
|
||||||
|
fixed profiler.html empty `href=""`→relative `.`/`console` (was JS-only/fragile; verified empty-href=0).
|
||||||
|
|
||||||
|
> CORRECTION LOG: first edit pass (earlier this session) FAILED silently — old_strings were guessed
|
||||||
|
> (`.ft a{margin:0 4px}`, a fake footer string, `ui-copilot/dashboard.html` path). Re-done with grep/Read-verified
|
||||||
|
> exact strings. The real dashboard file is `search.html` (route index.ts:1258), NOT `dashboard.html` (orphan) or `ui/`.
|
||||||
|
|
||||||
|
## (status note) — rounds 2 & 3 are recorded in the SHIPPED sections below; this block is superseded.
|
||||||
|
- #3 contract-card collapse → DONE round 2 (persistent `.card-top-toggle`).
|
||||||
|
- #5 declutter (⑤ relocate, ④ demote, ③ disclosure, Market Intelligence clarify, dead CSS) → DONE round 3.
|
||||||
|
- Still open: nav shared-component refactor (deferred, needs restart) + optional contract truncation (skipped on purpose). See "DELIBERATELY NOT DONE".
|
||||||
|
|
||||||
|
## Recommended execution order
|
||||||
|
1. New-tab attrs (lines 594-599, 781, 1024-1026) — trivial, high impact.
|
||||||
|
2. Global `.clickable` CSS helper + apply to onclick elements.
|
||||||
|
3. Collapsible affordance (chevron+label persistent, cursor, hover) on contract cards + section headers.
|
||||||
|
4. Default-collapse ⓪ narrative for returning users (localStorage).
|
||||||
|
5. Hierarchy/declutter (tiering, relocate ⑤ to proof, truncation).
|
||||||
|
6. Nav consistency pass across sibling files.
|
||||||
|
|
||||||
|
## VERIFY before claiming done (J's rules: test drilldowns, no greenwashing)
|
||||||
|
- `curl -s localhost:3700/ | grep target=_blank` confirms new-tab attrs present.
|
||||||
|
- Load https://devop.live/lakehouse/ in browser: click a contract card (expand+collapse visible),
|
||||||
|
hover a worker row (cursor+chevron), click reference nav (opens new tab), reload (intro stays collapsed).
|
||||||
|
- Don't restart the service for HTML-only edits.
|
||||||
|
|
||||||
|
## Audit provenance
|
||||||
|
5-dimension parallel Explore audit, run wf_c897f421-db1, full JSON at
|
||||||
|
`/tmp/claude-0/-home-profit/c6ca0218-678c-4a30-833c-1063e40e7f69/tasks/wm9x4y52d.output`.
|
||||||
|
NOTE: line numbers are audit estimates — `grep` to confirm exact lines before each Edit.
|
||||||
@ -74,6 +74,7 @@ input:focus{border-color:#388bfd}
|
|||||||
<nav>
|
<nav>
|
||||||
<a href=".">Dashboard</a>
|
<a href=".">Dashboard</a>
|
||||||
<a href="console">Walkthrough</a>
|
<a href="console">Walkthrough</a>
|
||||||
|
<a href="profiler">Profiler</a>
|
||||||
<a href="proof">Architecture</a>
|
<a href="proof">Architecture</a>
|
||||||
<a href="spec">Spec</a>
|
<a href="spec">Spec</a>
|
||||||
<a href="onboard">Onboard</a>
|
<a href="onboard">Onboard</a>
|
||||||
|
|||||||
@ -54,7 +54,7 @@ body{font-family:'Inter',-apple-system,system-ui,sans-serif;background:#090c10;c
|
|||||||
</head><body>
|
</head><body>
|
||||||
<div class="bar">
|
<div class="bar">
|
||||||
<h1>Staffing Co-Pilot · Contractor Profile</h1>
|
<h1>Staffing Co-Pilot · Contractor Profile</h1>
|
||||||
<a href="/">← Dashboard</a>
|
<a href=".">← Dashboard</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
|
|||||||
@ -91,6 +91,7 @@ table.preview tr:hover td{background:#0d1117}
|
|||||||
<nav>
|
<nav>
|
||||||
<a href=".">Dashboard</a>
|
<a href=".">Dashboard</a>
|
||||||
<a href="console">Walkthrough</a>
|
<a href="console">Walkthrough</a>
|
||||||
|
<a href="profiler">Profiler</a>
|
||||||
<a href="proof">Architecture</a>
|
<a href="proof">Architecture</a>
|
||||||
<a href="spec">Spec</a>
|
<a href="spec">Spec</a>
|
||||||
<a href="onboard" class="active">Onboard</a>
|
<a href="onboard" class="active">Onboard</a>
|
||||||
|
|||||||
@ -478,6 +478,15 @@ bun test auditor/schemas/distillation/ tests/distillation/
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="chapter">
|
||||||
|
<div class="num">Chapter 11</div>
|
||||||
|
<h2>Substrate signals — live architecture health</h2>
|
||||||
|
<div class="lede">Four live probes of the architecture itself, not the staffing workload: instant-search latency, index shape, playbook-memory depth, and pathway-matrix compounding. These answer "is the substrate healthy right now?" — moved here from the operator dashboard (2026-05-30) where they competed with the day's work.</div>
|
||||||
|
<div class="grid" id="arch-signals" style="grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px">
|
||||||
|
<div class="loading" style="grid-column:1/-1">Probing substrate…</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer">Lakehouse · Architecture page regenerates tests on every load · <a href="console">walkthrough</a> · <a href=".">dashboard</a></div>
|
<div class="footer">Lakehouse · Architecture page regenerates tests on every load · <a href="console">walkthrough</a> · <a href=".">dashboard</a></div>
|
||||||
@ -501,8 +510,40 @@ window.addEventListener('load',function(){
|
|||||||
loadLiveSections();
|
loadLiveSections();
|
||||||
loadPathwayLive();
|
loadPathwayLive();
|
||||||
loadSignalLive();
|
loadSignalLive();
|
||||||
|
loadArchSignals();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ⑤ Substrate Signals — moved from the operator dashboard (search.html)
|
||||||
|
// 2026-05-30 so the dashboard stays focused on staffing work and the
|
||||||
|
// architecture-health probes live with the rest of the architecture page.
|
||||||
|
// Uses apiPost (the /intelligence/arch_signals endpoint accepts GET or POST).
|
||||||
|
function loadArchSignals(){
|
||||||
|
var el=document.getElementById('arch-signals');
|
||||||
|
if(!el) return;
|
||||||
|
apiPost('/intelligence/arch_signals',{}).then(function(s){
|
||||||
|
el.textContent='';
|
||||||
|
function tile(label, big, sub, accent){
|
||||||
|
var t=document.createElement('div');
|
||||||
|
t.style.cssText='background:#0d1117;border:1px solid #171d27;border-radius:10px;padding:14px 16px;border-left:3px solid '+(accent||'#58a6ff');
|
||||||
|
var l=document.createElement('div');l.style.cssText='font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#545d68;margin-bottom:6px';l.textContent=label;
|
||||||
|
var b=document.createElement('div');b.style.cssText='font-size:20px;font-weight:600;color:#e6edf3;line-height:1.1';b.textContent=big;
|
||||||
|
var u=document.createElement('div');u.style.cssText='font-size:10px;color:#8b949e;margin-top:6px;line-height:1.4';u.textContent=sub;
|
||||||
|
t.appendChild(l);t.appendChild(b);t.appendChild(u);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
var idx=s.index||{};
|
||||||
|
var pbm=s.playbook_memory||{};
|
||||||
|
var pwm=s.pathway_memory||{};
|
||||||
|
var latencyColor=s.instant_search_probe_ms<100?'#2ea043':s.instant_search_probe_ms<500?'#d29922':'#f85149';
|
||||||
|
el.appendChild(tile('Instant Search',(s.instant_search_probe_ms||'?')+'ms','Live /vectors/hybrid probe · 500K-row index · '+(idx.chunk_count||0).toLocaleString()+' chunks',latencyColor));
|
||||||
|
el.appendChild(tile('Index',(idx.dimensions||768)+'d · '+(idx.model||'?'),(idx.source||'?')+' → '+(idx.name||'?')+' · '+(idx.backend||'parquet'),'#58a6ff'));
|
||||||
|
el.appendChild(tile('Playbook Memory',(pbm.entries||0).toLocaleString()+' entries',pbm.entries>0?'Meta-index active · boosts candidates from past fills':'Empty · POST /vectors/playbook_memory/rebuild to populate',pbm.entries>0?'#2ea043':'#d29922'));
|
||||||
|
el.appendChild(tile('Pathway Matrix',(pwm.total_pathways||0)+' traces',pwm.retired+' retired · '+pwm.total_replays+' replays · ADR-021 compounding','#58a6ff'));
|
||||||
|
}).catch(function(e){
|
||||||
|
el.textContent='substrate signals unavailable: '+e.message;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Pathway memory live counters in Chapter 4 — small inline spans.
|
// Pathway memory live counters in Chapter 4 — small inline spans.
|
||||||
function loadPathwayLive(){
|
function loadPathwayLive(){
|
||||||
fetch(A+'/api/vectors/pathway/stats').then(function(r){return r.json()}).then(function(p){
|
fetch(A+'/api/vectors/pathway/stats').then(function(r){return r.json()}).then(function(p){
|
||||||
|
|||||||
@ -135,6 +135,26 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
.ft{text-align:center;padding:24px;color:#3d444d;font-size:11px;border-top:1px solid #171d27;margin-top:32px}
|
.ft{text-align:center;padding:24px;color:#3d444d;font-size:11px;border-top:1px solid #171d27;margin-top:32px}
|
||||||
.ft a{color:#545d68;text-decoration:none;transition:color 0.15s}
|
.ft a{color:#545d68;text-decoration:none;transition:color 0.15s}
|
||||||
.ft a:hover{color:#e6edf3}
|
.ft a:hover{color:#e6edf3}
|
||||||
|
/* ── UX pass 2026-05-30: clearer interactive affordances ── */
|
||||||
|
[onclick]{cursor:pointer}
|
||||||
|
[role="button"]{cursor:pointer}
|
||||||
|
.iworker{cursor:pointer}
|
||||||
|
.iworker:hover{background:#1c2333;transform:translateY(-1px);box-shadow:0 2px 8px rgba(0,0,0,.3),0 0 0 1px #30363d;transition:background .15s,transform .15s,box-shadow .15s}
|
||||||
|
.iworker:active{transform:translateY(0);box-shadow:none}
|
||||||
|
details>summary{cursor:pointer}
|
||||||
|
details>summary:hover{color:#e6edf3;background:rgba(58,90,127,.15);border-radius:6px}
|
||||||
|
a:focus-visible,button:focus-visible,summary:focus-visible,[onclick]:focus-visible{outline:2px solid #388bfd;outline-offset:2px;border-radius:4px}
|
||||||
|
/* ③ example-search disclosure (2026-05-30) — collapsed by default, CSS-only hover/focus */
|
||||||
|
.samples-disclosure{font-size:11px}
|
||||||
|
.samples-summary{display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:#8b949e;list-style:none;padding:4px 0;user-select:none}
|
||||||
|
.samples-summary::-webkit-details-marker{display:none}
|
||||||
|
.samples-summary::before{content:'▸';display:inline-block;font-size:10px;transition:transform .15s}
|
||||||
|
.samples-disclosure[open] .samples-summary::before{transform:rotate(90deg)}
|
||||||
|
.samples-summary:hover{color:#e6edf3}
|
||||||
|
.samples-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
|
||||||
|
.search-chip{font-size:11px;padding:5px 10px;background:#161b22;border:1px solid #30363d;border-radius:14px;color:#8b949e;cursor:pointer;transition:border-color .15s,color .15s,background .15s}
|
||||||
|
.search-chip:hover{border-color:#58a6ff;color:#e6edf3;background:#1c2333}
|
||||||
|
.search-chip:focus-visible{outline:2px solid #388bfd;outline-offset:2px}
|
||||||
|
|
||||||
.ld{color:#3d444d;text-align:center;padding:40px;font-size:13px}
|
.ld{color:#3d444d;text-align:center;padding:40px;font-size:13px}
|
||||||
/* Reused pulse keyframe — shared by status dots in the market-pulse
|
/* Reused pulse keyframe — shared by status dots in the market-pulse
|
||||||
@ -336,6 +356,18 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
.contract-card.expanded .card-toggle .chevron { transform: rotate(180deg) }
|
.contract-card.expanded .card-toggle .chevron { transform: rotate(180deg) }
|
||||||
|
/* Persistent top-of-card expand affordance (2026-05-30 UX) — always
|
||||||
|
visible, button-styled so users immediately see the card expands. */
|
||||||
|
.contract-card .card-top-toggle {
|
||||||
|
display: inline-flex; align-items: center; gap: 6px;
|
||||||
|
padding: 4px 10px; margin-bottom: 10px;
|
||||||
|
font-size: 11px; font-weight: 600; color: #8b949e;
|
||||||
|
background: #161b22; border: 1px solid #30363d; border-radius: 7px;
|
||||||
|
cursor: pointer; user-select: none;
|
||||||
|
transition: background .15s, border-color .15s, color .15s;
|
||||||
|
}
|
||||||
|
.contract-card .card-top-toggle:hover { background: #1c2333; border-color: #58a6ff; color: #e6edf3 }
|
||||||
|
.contract-card .card-top-toggle .chevron { display:inline-block; font-size:12px; line-height:1 }
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.contract-card { transition: none }
|
.contract-card { transition: none }
|
||||||
.contract-card:hover { transform: none }
|
.contract-card:hover { transform: none }
|
||||||
@ -591,12 +623,12 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
<nav>
|
<nav>
|
||||||
<a href="." class="active">Dashboard</a>
|
<a href="." class="active">Dashboard</a>
|
||||||
<a href="console">Walkthrough</a>
|
<a href="console">Walkthrough</a>
|
||||||
<a href="profiler">Profiler</a>
|
<a href="profiler" target="_blank" rel="noopener">Profiler ↗</a>
|
||||||
<a href="proof">Architecture</a>
|
<a href="proof" target="_blank" rel="noopener">Architecture ↗</a>
|
||||||
<a href="spec">Spec</a>
|
<a href="spec" target="_blank" rel="noopener">Spec ↗</a>
|
||||||
<a href="onboard">Onboard</a>
|
<a href="onboard" target="_blank" rel="noopener">Onboard ↗</a>
|
||||||
<a href="alerts">Alerts</a>
|
<a href="alerts" target="_blank" rel="noopener">Alerts ↗</a>
|
||||||
<a href="workspaces">Workspaces</a>
|
<a href="workspaces" target="_blank" rel="noopener">Workspaces ↗</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="rt" id="status">Loading...</div>
|
<div class="rt" id="status">Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
@ -711,10 +743,15 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
|
|
||||||
<div class="section" id="market-section">
|
<div class="section" id="market-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<span class="section-title">Market Intelligence</span>
|
<span class="section-title">Market Intelligence — Chicago permit map</span>
|
||||||
<span class="section-meta">Public permit data · Updated live</span>
|
<span class="section-meta">Where the construction money is · live from data.cityofchicago.org</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="market"></div>
|
<p style="color:#8b949e;font-size:11px;margin:0 0 10px;line-height:1.5;max-width:680px">
|
||||||
|
The geographic companion to ① Live Market: every active building permit plotted
|
||||||
|
by location, sized by construction value. ① tells you <em>when</em> the shifts are;
|
||||||
|
this tells you <em>where</em> the work is.
|
||||||
|
</p>
|
||||||
|
<div id="market"><div style="color:#8b949e;font-size:11px;padding:8px 0">Loading Chicago permit map…</div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ═══ ③ Worker Search — natural-language lookup over the 500K bench ═══ -->
|
<!-- ═══ ③ Worker Search — natural-language lookup over the 500K bench ═══ -->
|
||||||
@ -747,12 +784,18 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ═══ ④ System Activity — what the substrate has learned to do ═══ -->
|
<!-- ═══ ④ System Activity — what the substrate has learned to do ═══ -->
|
||||||
<div class="section" id="learning-section">
|
<!-- 2026-05-30: demoted to a collapsed-by-default <details> (tier 3). It's
|
||||||
<div class="section-header">
|
capability/reference info, not the day's staffing work, so it no longer
|
||||||
|
competes for attention on every load. Mirrors the ⓪ legacy-bridge pattern:
|
||||||
|
ontoggle flips the ▸/▾ hint. loadLearning() still populates #learning. -->
|
||||||
|
<details class="section" id="learning-section"
|
||||||
|
ontoggle="var s=this.querySelector('.lr-toggle-hint');if(s)s.textContent=this.open?'▾ click to collapse':'▸ click to expand'">
|
||||||
|
<summary style="list-style:none;cursor:pointer;display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;outline:none">
|
||||||
<span class="section-title" style="color:#e6edf3;font-size:13px">④ System Activity — what the substrate has learned to do</span>
|
<span class="section-title" style="color:#e6edf3;font-size:13px">④ System Activity — what the substrate has learned to do</span>
|
||||||
<span class="section-meta">Live capabilities · pulled from each subsystem on load</span>
|
<span class="section-meta">Live capabilities · pulled from each subsystem on load</span>
|
||||||
</div>
|
<span class="lr-toggle-hint" style="margin-left:auto;font-size:10px;color:#545d68">▸ click to expand</span>
|
||||||
<p style="color:#8b949e;font-size:11px;margin:0 0 12px;line-height:1.5;max-width:780px">
|
</summary>
|
||||||
|
<p style="color:#8b949e;font-size:11px;margin:10px 0 12px;line-height:1.5;max-width:780px">
|
||||||
Each tile is a capability the system has acquired and the live metric proving
|
Each tile is a capability the system has acquired and the live metric proving
|
||||||
it's running. Operational learning (fills, playbooks, hot-swaps) compounds
|
it's running. Operational learning (fills, playbooks, hot-swaps) compounds
|
||||||
inside each capability; what changes here is the <em>set of things the
|
inside each capability; what changes here is the <em>set of things the
|
||||||
@ -760,25 +803,14 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
capability replicates by config, not code.
|
capability replicates by config, not code.
|
||||||
</p>
|
</p>
|
||||||
<div id="learning"></div>
|
<div id="learning"></div>
|
||||||
</div>
|
</details>
|
||||||
|
|
||||||
<!-- ═══ ⑤ Substrate signals — compact architecture-health strip (bottom) ═══ -->
|
<!-- ⑤ Substrate Signals (architecture-health probes) moved to the Architecture
|
||||||
<div class="section" id="arch-signals-section">
|
page (proof.html, Chapter 11) on 2026-05-30 — they measure the substrate,
|
||||||
<div class="section-header">
|
not the staffing workload, so they belong with the architecture story and
|
||||||
<span class="section-title" style="color:#e6edf3;font-size:13px">⑤ Substrate Signals — architecture health</span>
|
keep this operator dashboard focused on the day's work. Link in the footer. -->
|
||||||
<span class="section-meta">Live probes of the index, memory, and pathway layers</span>
|
|
||||||
</div>
|
|
||||||
<p style="color:#8b949e;font-size:11px;margin:0 0 10px;line-height:1.5;max-width:680px">
|
|
||||||
These tiles measure the architecture itself, not the staffing workload.
|
|
||||||
Instant-search latency, index shape, playbook-memory depth, pathway-matrix
|
|
||||||
compounding — four probes that answer "is the substrate healthy right now?"
|
|
||||||
</p>
|
|
||||||
<div id="arch-signals" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px">
|
|
||||||
<div style="color:#8b949e;font-size:11px;grid-column:1/-1">Probing substrate…</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ft" id="footer">Staffing Co-Pilot · Hybrid SQL + Vector Search · loading scale… · <a href="console">Console</a> · <a href="proof">Architecture</a></div>
|
<div class="ft" id="footer">Staffing Co-Pilot · Hybrid SQL + Vector Search · loading scale… · <a href="console">Console</a> · <a href="proof" target="_blank" rel="noopener">Architecture ↗</a></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ═══ Mobile section-jump dock — visible < 768px only via CSS ═══ -->
|
<!-- ═══ Mobile section-jump dock — visible < 768px only via CSS ═══ -->
|
||||||
@ -792,7 +824,7 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun
|
|||||||
<a href="#live-contracts-section" title="Open contracts + candidates">②<span class="dock-label">Jobs</span></a>
|
<a href="#live-contracts-section" title="Open contracts + candidates">②<span class="dock-label">Jobs</span></a>
|
||||||
<a href="#worker-search-section" title="Search 500K workers">③<span class="dock-label">Search</span></a>
|
<a href="#worker-search-section" title="Search 500K workers">③<span class="dock-label">Search</span></a>
|
||||||
<a href="#learning-section" title="What the substrate has learned">④<span class="dock-label">Learn</span></a>
|
<a href="#learning-section" title="What the substrate has learned">④<span class="dock-label">Learn</span></a>
|
||||||
<a href="#arch-signals-section" title="Live architecture health">⑤<span class="dock-label">Stack</span></a>
|
<a href="proof" title="Architecture & live substrate signals" target="_blank" rel="noopener">✦<span class="dock-label">Arch</span></a>
|
||||||
</nav>
|
</nav>
|
||||||
<script>
|
<script>
|
||||||
var P=location.pathname.indexOf('/lakehouse')>=0?'/lakehouse':'';
|
var P=location.pathname.indexOf('/lakehouse')>=0?'/lakehouse':'';
|
||||||
@ -826,7 +858,7 @@ function styleSkelStages(){
|
|||||||
}
|
}
|
||||||
window.addEventListener('load',function(){
|
window.addEventListener('load',function(){
|
||||||
styleSkelStages(); startSkelStages();
|
styleSkelStages(); startSkelStages();
|
||||||
loadSystemSummary();loadLegacyBridge();loadDay();loadStaffingForecast();loadLiveContracts();loadMarket();loadLearning();loadWorkerSearchSamples();loadArchSignals();loadStaffers();
|
loadSystemSummary();loadLegacyBridge();loadDay();loadStaffingForecast();loadLiveContracts();loadMarket();loadLearning();loadWorkerSearchSamples();loadStaffers();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Per-staffer hot-swap dropdown — runs independently of the simulation
|
// Per-staffer hot-swap dropdown — runs independently of the simulation
|
||||||
@ -989,6 +1021,15 @@ function loadWorkerSearchSamples(){
|
|||||||
{tag:'Specialist', q:'maintenance tech comfortable with Allen-Bradley PLCs'},
|
{tag:'Specialist', q:'maintenance tech comfortable with Allen-Bradley PLCs'},
|
||||||
{tag:'High-volume', q:'warehouse associates available next week near Indianapolis'}
|
{tag:'High-volume', q:'warehouse associates available next week near Indianapolis'}
|
||||||
];
|
];
|
||||||
|
// 2026-05-30: wrap the 6 example chips in a collapsed disclosure so they
|
||||||
|
// don't consume vertical space on every load. The chip keeps its tag+query
|
||||||
|
// two-span layout and scroll-into-view click; the disclosure just gates them.
|
||||||
|
el.textContent='';
|
||||||
|
var det=document.createElement('details');det.className='samples-disclosure';
|
||||||
|
var sum=document.createElement('summary');sum.className='samples-summary';
|
||||||
|
sum.textContent='Example searches';
|
||||||
|
det.appendChild(sum);
|
||||||
|
var row=document.createElement('div');row.className='samples-row';
|
||||||
samples.forEach(function(s){
|
samples.forEach(function(s){
|
||||||
var chip=document.createElement('button');
|
var chip=document.createElement('button');
|
||||||
chip.type='button';
|
chip.type='button';
|
||||||
@ -1002,8 +1043,10 @@ function loadWorkerSearchSamples(){
|
|||||||
var input=document.getElementById('sq');
|
var input=document.getElementById('sq');
|
||||||
if(input){input.value=s.q;doSearch();input.scrollIntoView({behavior:'smooth',block:'center'});}
|
if(input){input.value=s.q;doSearch();input.scrollIntoView({behavior:'smooth',block:'center'});}
|
||||||
};
|
};
|
||||||
el.appendChild(chip);
|
row.appendChild(chip);
|
||||||
});
|
});
|
||||||
|
det.appendChild(row);
|
||||||
|
el.appendChild(det);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSystemSummary(){
|
function loadSystemSummary(){
|
||||||
@ -1023,7 +1066,7 @@ function loadSystemSummary(){
|
|||||||
foot.appendChild(document.createTextNode('Staffing Co-Pilot · Hybrid SQL + Vector Search · '+totalRows+' rows across '+ds+' datasets · '+chunks+' vector chunks · '));
|
foot.appendChild(document.createTextNode('Staffing Co-Pilot · Hybrid SQL + Vector Search · '+totalRows+' rows across '+ds+' datasets · '+chunks+' vector chunks · '));
|
||||||
var a1=document.createElement('a');a1.href='console';a1.textContent='Console';foot.appendChild(a1);
|
var a1=document.createElement('a');a1.href='console';a1.textContent='Console';foot.appendChild(a1);
|
||||||
foot.appendChild(document.createTextNode(' · '));
|
foot.appendChild(document.createTextNode(' · '));
|
||||||
var a2=document.createElement('a');a2.href='proof';a2.textContent='Architecture';foot.appendChild(a2);
|
var a2=document.createElement('a');a2.href='proof';a2.target='_blank';a2.rel='noopener';a2.textContent='Architecture ↗';foot.appendChild(a2);
|
||||||
}
|
}
|
||||||
// Also update the collapsible search box label if not yet populated
|
// Also update the collapsible search box label if not yet populated
|
||||||
var sum=document.querySelector('.sa summary');
|
var sum=document.querySelector('.sa summary');
|
||||||
@ -1033,56 +1076,9 @@ function loadSystemSummary(){
|
|||||||
}).catch(function(){/* non-fatal */});
|
}).catch(function(){/* non-fatal */});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Substrate signals: render the 4 architecture-health tiles ───
|
// ⑤ loadArchSignals() was MOVED to proof.html (Architecture, Chapter 11)
|
||||||
function loadArchSignals(){
|
// on 2026-05-30 — the architecture-health probes live with the rest of the
|
||||||
var el=document.getElementById('arch-signals');
|
// architecture story now, so the dashboard stays focused on staffing work.
|
||||||
api('/intelligence/arch_signals',{}).then(function(s){
|
|
||||||
el.textContent='';
|
|
||||||
function tile(label, big, sub, accent){
|
|
||||||
var t=document.createElement('div');
|
|
||||||
t.style.cssText='background:#0d1117;border:1px solid #171d27;border-radius:10px;padding:14px 16px;border-left:3px solid '+(accent||'#58a6ff');
|
|
||||||
var l=document.createElement('div');l.style.cssText='font-size:10px;text-transform:uppercase;letter-spacing:1px;color:#545d68;margin-bottom:6px';l.textContent=label;
|
|
||||||
var b=document.createElement('div');b.style.cssText='font-size:20px;font-weight:600;color:#e6edf3;line-height:1.1';b.textContent=big;
|
|
||||||
var u=document.createElement('div');u.style.cssText='font-size:10px;color:#8b949e;margin-top:6px;line-height:1.4';u.textContent=sub;
|
|
||||||
t.appendChild(l);t.appendChild(b);t.appendChild(u);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
var idx=s.index||{};
|
|
||||||
var pbm=s.playbook_memory||{};
|
|
||||||
var pwm=s.pathway_memory||{};
|
|
||||||
// Tile 1 — instant search (the "we cleverly indexed at ingest" claim)
|
|
||||||
var latencyColor=s.instant_search_probe_ms<100?'#2ea043':s.instant_search_probe_ms<500?'#d29922':'#f85149';
|
|
||||||
el.appendChild(tile(
|
|
||||||
'Instant Search',
|
|
||||||
(s.instant_search_probe_ms||'?')+'ms',
|
|
||||||
'Live /vectors/hybrid probe · 500K-row index · '+(idx.chunk_count||0).toLocaleString()+' chunks',
|
|
||||||
latencyColor
|
|
||||||
));
|
|
||||||
// Tile 2 — index shape (hot-swap claim)
|
|
||||||
el.appendChild(tile(
|
|
||||||
'Index',
|
|
||||||
(idx.dimensions||768)+'d · '+(idx.model||'?'),
|
|
||||||
(idx.source||'?')+' → '+(idx.name||'?')+' · '+(idx.backend||'parquet'),
|
|
||||||
'#58a6ff'
|
|
||||||
));
|
|
||||||
// Tile 3 — self-regulating memory
|
|
||||||
el.appendChild(tile(
|
|
||||||
'Playbook Memory',
|
|
||||||
(pbm.entries||0).toLocaleString()+' entries',
|
|
||||||
pbm.entries>0?'Meta-index active · boosts candidates from past fills':'Empty · POST /vectors/playbook_memory/rebuild to populate',
|
|
||||||
pbm.entries>0?'#2ea043':'#d29922'
|
|
||||||
));
|
|
||||||
// Tile 4 — ADR-021 pathway compounding
|
|
||||||
el.appendChild(tile(
|
|
||||||
'Pathway Matrix',
|
|
||||||
(pwm.total_pathways||0)+' traces',
|
|
||||||
pwm.retired+' retired · '+pwm.total_replays+' replays · ADR-021 compounding',
|
|
||||||
'#58a6ff'
|
|
||||||
));
|
|
||||||
}).catch(function(e){
|
|
||||||
el.textContent='substrate signals unavailable: '+e.message;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── Live Market hero: 24/7 shift clock (left) + Chicago permit pulse (right) ──
|
// ─── Live Market hero: 24/7 shift clock (left) + Chicago permit pulse (right) ──
|
||||||
// Combines two previously-separate tiles into one coherent "what's happening in
|
// Combines two previously-separate tiles into one coherent "what's happening in
|
||||||
@ -2534,6 +2530,15 @@ function loadLiveContracts(){
|
|||||||
right.appendChild(rate);
|
right.appendChild(rate);
|
||||||
}
|
}
|
||||||
hdr.appendChild(left);hdr.appendChild(right);card.appendChild(hdr);
|
hdr.appendChild(left);hdr.appendChild(right);card.appendChild(hdr);
|
||||||
|
// Persistent expand affordance at the TOP of the card (2026-05-30
|
||||||
|
// UX). The whole card is already clickable; this makes the toggle
|
||||||
|
// obvious and shows expand state in BOTH collapsed and expanded
|
||||||
|
// form. Text + chevron are flipped by the card click handler below.
|
||||||
|
var topToggle=document.createElement('div');topToggle.className='card-top-toggle';
|
||||||
|
var topChev=document.createElement('span');topChev.className='chevron';topChev.textContent='▸';
|
||||||
|
var topLabel=document.createElement('span');topLabel.textContent='Show details';
|
||||||
|
topToggle.appendChild(topChev);topToggle.appendChild(topLabel);
|
||||||
|
card.appendChild(topToggle);
|
||||||
// Architecture pill row — instant-search latency + shift coverage
|
// Architecture pill row — instant-search latency + shift coverage
|
||||||
// + pool-size proof that the index actually fired on this call.
|
// + pool-size proof that the index actually fired on this call.
|
||||||
// This is the "our substrate is better" surface J asked for.
|
// This is the "our substrate is better" surface J asked for.
|
||||||
@ -2853,6 +2858,8 @@ function loadLiveContracts(){
|
|||||||
toggleLabel.textContent=nowExpanded
|
toggleLabel.textContent=nowExpanded
|
||||||
? 'click to collapse'
|
? 'click to collapse'
|
||||||
: 'click for full curve, economics, candidates, project index';
|
: 'click for full curve, economics, candidates, project index';
|
||||||
|
topLabel.textContent=nowExpanded?'Hide details':'Show details';
|
||||||
|
topChev.textContent=nowExpanded?'▾':'▸';
|
||||||
// Auto-open the Project Index ONLY on user-driven expand. This
|
// Auto-open the Project Index ONLY on user-driven expand. This
|
||||||
// avoids firing 20+ OSHA scrapes on page load — each open
|
// avoids firing 20+ OSHA scrapes on page load — each open
|
||||||
// triggers /intelligence/permit_entities, which live-scrapes
|
// triggers /intelligence/permit_entities, which live-scrapes
|
||||||
|
|||||||
@ -102,6 +102,7 @@ h2{color:#e6edf3;font-size:22px;font-weight:700;letter-spacing:-0.3px;margin-bot
|
|||||||
<nav>
|
<nav>
|
||||||
<a href=".">Dashboard</a>
|
<a href=".">Dashboard</a>
|
||||||
<a href="console">Walkthrough</a>
|
<a href="console">Walkthrough</a>
|
||||||
|
<a href="profiler">Profiler</a>
|
||||||
<a href="proof">Architecture</a>
|
<a href="proof">Architecture</a>
|
||||||
<a href="spec">Spec</a>
|
<a href="spec">Spec</a>
|
||||||
<a href="onboard">Onboard</a>
|
<a href="onboard">Onboard</a>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user