fix(curation): kill dev-artefact leak + rename agent honestly
Oracle remediation batch 1 — closing gaps #1 (agent overclaim), #4 (demo-data leak), #5 (raw-ID exposure): - src/lib/flowCuration.ts: shared isDevArtefact + curatedPublishedFlows filter for the whole codebase. Patterns drop rv_/orphan/Atlas F1/MCP SDX/Codex Test/sidekick/process_<ts>/backfill/smoke/probe/fixture and the EA2_* internal source_contexts. - src/scenes/Hub.tsx: loadPublishedFlows uses the shared curator - src/lib/agentTools.ts: list_processes and start_process both use the shared curator; raw transaction_id no longer in start reply - src/state/store.ts: snapshot + live merges curated; resolveDefaultStepId guards against scenarios whose defaultStepId references a stale step - src/scenes/Wizard.tsx: 'Process definition <hex>' confirmation replaced with the user-facing process name - src/scenes/Hub.tsx: start toast no longer shows transaction_id prefix - src/scenes/Agent.tsx + App.tsx + Landing.tsx: rename Pi -> FlowMaster Command Assistant. Welcome message says explicitly that this is a deterministic router and the LLM agent + tenant memory are on the roadmap. Tab label, hub chip, turn author all rebranded. - src/scenes/GeoAttendance.tsx: scene re-titled to 'Attendance map · preview' with honest copy explaining the dataset is illustrative until the EA2 attendance feed is wired in. - src/data/synthetic.ts: orphaned from runtime (kept in tree for tests). Snapshot now sources only the live-cached EA2 read (scenarios.json), filtered through the same curator. 29/29 tests green. No more 'rv test flow 0' / 'orphan' / 'Atlas F1' / raw 32-char hex IDs visible to a buyer.
This commit is contained in:
@@ -28,7 +28,7 @@ export default function Agent() {
|
||||
role: "agent",
|
||||
ok: true,
|
||||
text:
|
||||
`Hi ${userEmail.split("@")[0]}. I'm Pi — your FlowMaster co-pilot. I can navigate the cockpit, start processes, message your team, and walk you through the Studio.`,
|
||||
`Hi ${userEmail.split("@")[0]}. I'm the FlowMaster Command Assistant. I understand a fixed set of commands today and run them against the real EA2 backend — navigate, list processes, start a process, message a teammate, open the Studio. A natural-language LLM and per-tenant memory are on the roadmap.`,
|
||||
},
|
||||
]);
|
||||
const [draft, setDraft] = useState("");
|
||||
@@ -63,8 +63,9 @@ export default function Agent() {
|
||||
<div className="agent-scene">
|
||||
<aside className="agent-sidebar">
|
||||
<header className="agent-side-head">
|
||||
<div className="mc-hero-eyebrow"><Bot size={12} /> Pi — FlowMaster Agent</div>
|
||||
<h2 className="mc-hero-title">Talk to your cockpit</h2>
|
||||
<div className="mc-hero-eyebrow"><Bot size={12} /> FlowMaster Command Assistant</div>
|
||||
<h2 className="mc-hero-title">Tell the cockpit what to do</h2>
|
||||
<p className="agent-side-sub">Deterministic command router today. An LLM-backed agent with per-tenant memory is the next milestone.</p>
|
||||
</header>
|
||||
<div className="agent-tool-list">
|
||||
<div className="agent-tool-label">CAPABILITIES</div>
|
||||
@@ -84,11 +85,11 @@ export default function Agent() {
|
||||
<div className="agent-messages" ref={scrollRef}>
|
||||
{turns.map((t) => (
|
||||
<div key={t.id} className={`agent-turn agent-turn-${t.role}${t.ok === false ? " agent-turn-err" : ""}`}>
|
||||
<div className="agent-turn-author">{t.role === "user" ? userEmail.split("@")[0] : "Pi"}</div>
|
||||
<div className="agent-turn-author">{t.role === "user" ? userEmail.split("@")[0] : "Assistant"}</div>
|
||||
<div className="agent-turn-body">{t.text}</div>
|
||||
</div>
|
||||
))}
|
||||
{working && <div className="agent-turn agent-turn-agent agent-turn-thinking">Pi is thinking…</div>}
|
||||
{working && <div className="agent-turn agent-turn-agent agent-turn-thinking">Working…</div>}
|
||||
</div>
|
||||
|
||||
{turns.length <= 1 && (
|
||||
|
||||
@@ -69,10 +69,10 @@ export default function GeoAttendance() {
|
||||
return (
|
||||
<div className="geo-scene">
|
||||
<header className="geo-head">
|
||||
<div className="mc-hero-eyebrow"><Pulse size={12} /> Real-time attendance</div>
|
||||
<h2 className="mc-hero-title">Where your people are right now</h2>
|
||||
<div className="mc-hero-eyebrow"><Pulse size={12} /> Attendance map · preview</div>
|
||||
<h2 className="mc-hero-title">Where your people are</h2>
|
||||
<p className="geo-intro">
|
||||
Live attendance for stores, offices, and warehouses. Click a marker to see who's checked in and when. Powered by OpenStreetMap tiles — no proprietary mapping key required.
|
||||
Preview of the manager attendance view. Markers are illustrative until the attendance feed is wired up against the EA2 runtime; once connected, statuses come from real check-in events. Tiles are served by OpenStreetMap.
|
||||
</p>
|
||||
<div className="geo-stats">
|
||||
<span className="geo-stat geo-stat-ok">{stats.onSite} on-site</span>
|
||||
|
||||
+9
-21
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
|
||||
import { useApp } from "../state/store";
|
||||
import { api } from "../lib/api";
|
||||
import { wizardApi } from "../lib/wizardApi";
|
||||
import { curatedPublishedFlows } from "../lib/flowCuration";
|
||||
import { Branch, Layers, Pulse } from "../components/icons";
|
||||
|
||||
export type HubKey = "procurement" | "hr" | "it";
|
||||
@@ -57,32 +58,18 @@ interface PublishedFlow {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
const NON_BUSINESS_SOURCE_CONTEXTS = new Set([
|
||||
"EA2_CHAT_THREAD",
|
||||
"EA2_CHAT_MSG",
|
||||
"EA2_WIZARD_STEP",
|
||||
]);
|
||||
|
||||
async function loadPublishedFlows(): Promise<PublishedFlow[]> {
|
||||
const res = await fetch(`${api.config.baseUrl}/api/ea2/flow/processes?limit=200`, {
|
||||
headers: { Authorization: `Bearer ${sessionStorage.getItem("fm.mc.token.v1")}` },
|
||||
});
|
||||
if (!res.ok) throw new Error(`processes ${res.status}`);
|
||||
const body = await res.json();
|
||||
return ((body?.items || []) as any[])
|
||||
.filter(
|
||||
(it) =>
|
||||
it.status === "published" &&
|
||||
it.kind === "definition" &&
|
||||
it.display_name &&
|
||||
!NON_BUSINESS_SOURCE_CONTEXTS.has(it.source_context)
|
||||
)
|
||||
.map((it) => ({
|
||||
_key: it._key,
|
||||
display_name: it.display_name,
|
||||
description: it.description,
|
||||
name: it.name,
|
||||
}));
|
||||
return curatedPublishedFlows((body?.items || []) as any[]).map((it) => ({
|
||||
_key: it._key,
|
||||
display_name: it.display_name!,
|
||||
description: it.description,
|
||||
name: it.name,
|
||||
}));
|
||||
}
|
||||
|
||||
export default function Hub({ hub }: { hub: HubKey }) {
|
||||
@@ -110,7 +97,8 @@ export default function Hub({ hub }: { hub: HubKey }) {
|
||||
setBusy(flowKey);
|
||||
try {
|
||||
const res = await wizardApi.startInstance(flowKey, subject);
|
||||
pushToast("ok", `Started ${label}${subject ? ` for ${subject}` : ""} — ${res.transaction_id?.slice(0, 8) || "ok"}`);
|
||||
void res;
|
||||
pushToast("ok", `Started ${label}${subject ? ` for ${subject}` : ""}.`);
|
||||
setScene("mission");
|
||||
} catch (err: any) {
|
||||
pushToast("err", `Start failed: ${err.message}`);
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function Landing() {
|
||||
<button className="hub-chip" onClick={() => setScene("hub-hr")}>People Hub</button>
|
||||
<button className="hub-chip" onClick={() => setScene("hub-it")}>IT Hub</button>
|
||||
<button className="hub-chip" onClick={() => setScene("geo-attendance")}>Attendance Map</button>
|
||||
<button className="hub-chip" onClick={() => setScene("agent")}>Talk to Pi</button>
|
||||
<button className="hub-chip" onClick={() => setScene("agent")}>Command Assistant</button>
|
||||
<button className="hub-chip" onClick={() => setScene("chat")}>Team Chat</button>
|
||||
<button className="hub-chip" onClick={() => setScene("explainer")}>What is FlowMaster?</button>
|
||||
</div>
|
||||
|
||||
@@ -403,7 +403,7 @@ export default function Wizard() {
|
||||
<div className="wizard-panel success-panel">
|
||||
<div className="success-icon"><Check size={32} /></div>
|
||||
<h3 className="panel-h">Process Published!</h3>
|
||||
<p>Process definition <code>{publishedKey}</code> is now active in EA2.</p>
|
||||
<p>Your process <strong>{draft.name || "Untitled"}</strong> is now active and ready to run.</p>
|
||||
<div className="actions-row">
|
||||
<button className="btn btn-secondary" onClick={() => { setDraft({ step: "Intake", name: "", description: "", nodes: [], edges: [], fields: [], rules: [] }); setPublishedKey(null); }}>Create Another</button>
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user