From a117ae8b384b6c0d1202bfcf6dfb110f481da779 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 20 Apr 2026 18:36:51 -0500 Subject: [PATCH] =?UTF-8?q?Workspace=20UI=20=E2=80=94=20surface=20Phase=20?= =?UTF-8?q?8.5=20per-contract=20state=20+=20handoff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 8.5 was fully built on the Rust side (WorkspaceManager with create/handoff/search/shortlist/activity/get/list, persisted to object storage, zero-copy handoff between agents). Nothing surfaced it in the recruiter UI. This page closes that gap. /workspaces — split-pane UI: Left: scrollable list of all workspaces, sorted by updated_at. Each card shows name, tier pill (daily/weekly/monthly/pinned), current owner, count of shortlisted candidates + activity events. Right: selected workspace detail with five sections: 1. Header — name, tier, owner, created/updated dates, description, previous-owners audit trail (each handoff is preserved) 2. Actions row — Hand off, Shortlist candidate, Save search, Log activity 3. Shortlist — candidates flagged with dataset + record_id + notes 4. Saved searches — named SQL queries the staffer wants to rerun 5. Activity — chronological (newest first) log of what happened Four modals for the add/edit actions (create, handoff, shortlist, save-search, log-activity). All forms POST through the existing /api/* passthrough to the gateway's /workspaces/* routes. End-to-end verified live: 1. Sarah creates 'Demo: Toledo Week 17' workspace 2. Shortlists Helen Sanchez (W500K-4661) with notes about prior endorsements 3. Logs activity: 'called — Helen confirmed Tuesday 7am shift' 4. Hands off to Kim with reason 'end of shift' 5. Kim opens the workspace: owner=kim, previous_owners=[{sarah→kim}], sees all 3 prior events + the shortlisted Helen — no data copy, pointer swap only (Phase 8.5 design) Security: all dynamic content built via el(tag,cls,text) DOM helper. Zero innerHTML on API-derived strings. Modal close-on-backdrop-click is guarded to the backdrop element. Nav updated across all 7 pages. Workspaces is the 7th tab. Dashboard · Walkthrough · Architecture · Spec · Onboard · Alerts · Workspaces. --- mcp-server/alerts.html | 1 + mcp-server/console.html | 1 + mcp-server/index.ts | 10 + mcp-server/onboard.html | 1 + mcp-server/proof.html | 1 + mcp-server/search.html | 1 + mcp-server/spec.html | 1 + mcp-server/workspaces.html | 487 +++++++++++++++++++++++++++++++++++++ 8 files changed, 503 insertions(+) create mode 100644 mcp-server/workspaces.html diff --git a/mcp-server/alerts.html b/mcp-server/alerts.html index beb3c90..5378f28 100644 --- a/mcp-server/alerts.html +++ b/mcp-server/alerts.html @@ -78,6 +78,7 @@ input:focus{border-color:#388bfd} Spec Onboard Alerts + Workspaces diff --git a/mcp-server/console.html b/mcp-server/console.html index 87c7066..e89bcc9 100644 --- a/mcp-server/console.html +++ b/mcp-server/console.html @@ -99,6 +99,7 @@ details .body{padding-top:10px;font-size:12px;color:#8b949e} Spec Onboard Alerts + Workspaces
Reading live state…
diff --git a/mcp-server/index.ts b/mcp-server/index.ts index bc3e1f9..f6ec07e 100644 --- a/mcp-server/index.ts +++ b/mcp-server/index.ts @@ -660,6 +660,16 @@ async function main() { }); } + // Workspaces — per-contract state (Phase 8.5). UI layer over the + // gateway's /workspaces/* routes: list, create, detail, handoff, + // save-search, shortlist, log-activity. All persisted on the + // Rust side; this page is a pure viewer + editor. + if (url.pathname === "/workspaces") { + return new Response(Bun.file(import.meta.dir + "/workspaces.html"), { + headers: { ...cors, "Content-Type": "text/html" }, + }); + } + // Alerts — push/daemon settings page + config API + test-fire. if (url.pathname === "/alerts") { return new Response(Bun.file(import.meta.dir + "/alerts.html"), { diff --git a/mcp-server/onboard.html b/mcp-server/onboard.html index 1d585ec..21b7602 100644 --- a/mcp-server/onboard.html +++ b/mcp-server/onboard.html @@ -95,6 +95,7 @@ table.preview tr:hover td{background:#0d1117} Spec Onboard Alerts + Workspaces
30 minutes from CSV to live search
diff --git a/mcp-server/proof.html b/mcp-server/proof.html index 6a769e4..ceb428a 100644 --- a/mcp-server/proof.html +++ b/mcp-server/proof.html @@ -85,6 +85,7 @@ pre{background:#161b22;border:1px solid #171d27;border-radius:8px;padding:14px 1 Spec Onboard Alerts + Workspaces
Running live tests…
diff --git a/mcp-server/search.html b/mcp-server/search.html index 2a0cf1d..c4c95f4 100644 --- a/mcp-server/search.html +++ b/mcp-server/search.html @@ -108,6 +108,7 @@ body{font-family:'Inter',-apple-system,system-ui,'Segoe UI',sans-serif;backgroun Spec Onboard Alerts + Workspaces
Loading...
diff --git a/mcp-server/spec.html b/mcp-server/spec.html index 0753701..1b38c86 100644 --- a/mcp-server/spec.html +++ b/mcp-server/spec.html @@ -82,6 +82,7 @@ table.plain tr:hover td{background:#0d1117} Spec Onboard Alerts + Workspaces
v1 · 2026-04-20
diff --git a/mcp-server/workspaces.html b/mcp-server/workspaces.html new file mode 100644 index 0000000..d73b59f --- /dev/null +++ b/mcp-server/workspaces.html @@ -0,0 +1,487 @@ + + + +Lakehouse — Workspaces + + + +
+

Lakehouse — Workspaces

+ +
+ +
+ +
+

Per-contract workspaces

+
+ Each contract gets its own workspace: saved searches, shortlisted candidates, activity log, tier (daily / weekly / monthly / pinned). Persisted across sessions. One-click zero-copy handoff between staffers — Sarah hands off to Kim, Kim opens the workspace and sees everything Sarah saw. This is the layer that keeps institutional memory per-contract, not per-person. +
+ +
+ +
+
Loading workspaces…
+
+
Select a workspace from the list, or create one.
+
+
+ +
+ + + + + + + + + + + + + + + +