commit 3ffd0e68a7b6a79b4a15b3458a99d5c456aae05f Author: Shad Date: Sun Jun 14 00:09:32 2026 +0400 Mission Control demo v2 Polished command-center for FlowMaster with two data modes: - SNAPSHOT: bundled src/scenarios.json from demo.flow-master.ai - LIVE: in-browser fetch via src/lib/api.ts (dev-login + bearer) Scenarios: - procurement, extra-1, extra-2 (live from EA2) - ar, hcm, gl, service (industry blueprints, same typed shell) Honesty pass after Oracle review: - No invented numbers (Telemetry derives SLA + agent acceptance from real data) - Preview-only actions fire toasts naming the endpoint to wire them - Blueprint tours framed as 'industry blueprint', not 'we don't have this yet' - Mode pill + last-fetch age + refresh in topbar - Dev CORS dodged via vite proxy; production deploys same-origin 18 vitest tests + 26 playwright smoke assertions + DOM layout audit. Constraint: cross-origin live mode rejected by browser → fall back to snapshot Rejected: hardcoded SLA % | dishonest demo metrics Directive: wire preview-only action handlers to /api/runtime/transactions/{id}/actions to ship them for real Confidence: high Scope-risk: narrow Not-tested: production deployment via flowmaster-ops overlay diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed9b07e --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Build +node_modules +dist +dist-ssr +*.local + +# Logs +*.log +npm-debug.log* +pnpm-debug.log* + +# Editor +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store + +# QA artifacts (regenerated) +qa/screenshots/ + +# TypeScript build info +*.tsbuildinfo diff --git a/README.md b/README.md new file mode 100644 index 0000000..7e1588b --- /dev/null +++ b/README.md @@ -0,0 +1,152 @@ +# FlowMaster — Mission Control demo + +A polished, presenter-ready command-center for FlowMaster. Lives at +[`shad/flowmaster-mission-control-demo`](https://gitea.flow-master.ai/shad/flowmaster-mission-control-demo) +on Gitea. + +## What this is (and isn't) + +**Is:** + +- A single-page React 19 app (Vite + ReactFlow + cmdk + framer-motion + zustand + + dagre). +- Polished command-center for any FlowMaster process: graph, queue, inspector, + tour, command palette, live-mode toggle, run history. +- Two data modes: + - **SNAPSHOT** (default): bundled `src/scenarios.json`, captured from + `demo.flow-master.ai`. Fast, offline, deterministic. + - **LIVE**: in-browser fetch from the same backend via the API client at + `src/lib/api.ts` (dev-login → bearer → `/api/ea2/work-items` → + `/api/ea2/process-definitions/{k}/graph` → `/api/runtime/transactions/{id}`). + Loading and error states are wired through `src/scenes/MissionControl.tsx`. + +**Isn't:** + +- Not a replacement for the existing demo at https://demo.flow-master.ai + (Next.js fm-shell). This is a separate command-center experience. +- Not multi-tenant. No auth UI, no tenancy switcher, no settings. +- Not wired to actually mutate state. Every action button (start runtime, + dispatch agent, approve, decline, confirm) is **preview-only** and fires a + toast naming the endpoint that would make it real. + +## Scenarios in the catalog + +| id | mode | source | +| ----------- | --------- | ------------------------------------------------------------------- | +| procurement | live | Purchase Requisition → PO (`pr_to_po_def` on demo.flow-master.ai) | +| extra-1 | live | Atlas F1 Fresh (procurement variant) | +| extra-2 | live | Atlas F1 Fresh (procurement variant) | +| ar | blueprint | AR · Customer Refund Approval | +| hcm | blueprint | HCM · New Hire Onboarding | +| gl | blueprint | GL · Period-End Close | +| service | blueprint | Service Ops · Customer Incident | + +**Live** = backed by a real EA2 process definition currently in the demo +backend, with real runtime transactions and a real work-item queue. + +**Blueprint** = hand-modelled in the same typed format. Identical UI surface; +the backend just doesn't have a runnable definition for it yet. Internal +metadata carries `isSynthetic: true` for provenance audits. + +## How honesty is enforced in this code + +This pass came out of an Oracle review that called out theatrical bits in the +prior version. Safeguards now in place: + +- **No invented numbers.** `src/components/Telemetry.tsx` derives every value + from the active scenarios (`SLA = 1 - errored / cases`, agent acceptance = + fraction of agent runs not in `proposed`). The throughput sparkline plots + the actual `running` rollup over time, not a sine wave. The "ui tick" dot + is labelled as a UI heartbeat and tooltip-named as such. +- **No fake buttons.** Every preview-only action fires a toast that names the + endpoint that would make it real, and carries a `preview` marker. +- **No misleading tour copy.** Blueprint tours frame the scenario as an + industry blueprint, not "we don't have this yet". +- **Mode is always visible.** Topbar has a `SNAPSHOT`/`LIVE` pill, last-fetch + age, and a refresh button when live. + +## Live-mode mechanics (the CORS gotcha) + +`demo.flow-master.ai` does not advertise CORS headers for arbitrary origins. + +- In **dev** (`pnpm dev`): Vite proxies `/api/*` to + `${VITE_FM_BASE:-https://demo.flow-master.ai}` (see `vite.config.ts`). The + browser sees a same-origin request, no CORS check. `src/lib/api.ts` uses an + empty `baseUrl` in dev for this. +- In **production**: deploy the build at the same origin as the backend (or + behind a reverse proxy that passes `/api/*` through). Cross-origin + deployments fail gracefully — `setMode("live")` catches the error, surfaces + it in the topbar banner and a toast, and falls back to snapshot mode. + +## Run, test, build + +```bash +pnpm install + +# refresh the bundled snapshot from demo.flow-master.ai +pnpm fetch:scenarios + +# dev (with backend proxy for live mode) +pnpm dev # → http://127.0.0.1:5173 + +# tests +pnpm test # vitest, 18 tests across api, live, + # synthetic, layout + +# build +pnpm build # tsc + vite, single chunk ~225 KB gz + +# end-to-end smoke + screenshots +pnpm qa:smoke # playwright headless, 26 assertions + +# DOM layout audit +pnpm qa:layout +``` + +## File map + +``` +src/ +├── data/ # ProcessScenario domain + snapshot + blueprint catalog +├── lib/ # API client + live-scenario builder (+ tests) +├── state/store.ts # zustand: scene, mode, scenario, tour, recents, toasts +├── graph/layout.ts # dagre LR auto-layout (+ tests) +├── components/ # ProcessGraph, Inspector, LeftRail, CommandBar, Tour, +│ # Telemetry, Toaster, icons +├── scenes/ # Landing, MissionControl, RunHistory +├── App.tsx # shell: topbar (mode pill / refresh / tour / ⌘K) +├── index.css # design system (~700 lines) +├── main.tsx +└── scenarios.json # cached snapshot of demo.flow-master.ai + +qa/ +├── smoke.mjs # Playwright e2e + 9 screenshots +└── layout_audit.mjs # programmatic clipping/overlap check + +vite.config.ts # /api → demo.flow-master.ai proxy for dev +fetch_scenarios.mjs # Node script to refresh src/scenarios.json +``` + +## Deploy + +Production deployment is tracked in `FM06/flowmaster-ops` under +`manifests/overlays/mc.flow-master.ai/`. A static nginx serves `dist/`; +ingress fronts it at `mc.flow-master.ai`. `/api/*` is reverse-proxied to the +same backend `demo.flow-master.ai` talks to — that's what makes live mode +work in production without CORS. + +```bash +pnpm build +# dist/ is the static site → ship to nginx referenced by the ops overlay +``` + +## What's intentionally not here + +- Authentication UI (dev-login is used because this is a demo lane). +- Mutation endpoints (every action is preview-only and the toast names the + endpoint). +- Mobile layout (1440px-and-up demo surface). +- Route persistence / deep linking (scene + scenario live in memory). +- i18n (English only). + +Small, well-scoped follow-ups — not architectural changes. diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..ef614d2 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,22 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + globals: globals.browser, + }, + }, +]) diff --git a/fetch_scenarios.mjs b/fetch_scenarios.mjs new file mode 100644 index 0000000..001d60c --- /dev/null +++ b/fetch_scenarios.mjs @@ -0,0 +1,200 @@ +// Multi-scenario live read from demo.flow-master.ai. +// +// Strategy: +// 1. dev-login → bearer token +// 2. /api/ea2/work-items?view=all → enumerate every definition_key +// actually referenced by live work, then count cases per definition. +// 3. For each top-N definition, fetch its graph (`/api/ea2/process-definitions/{k}/graph`) +// and a few full runtime transactions. +// 4. Classify into family buckets (procurement/AR/HCM/GL close/service ops) +// using definition display_name + node labels. +// 5. Write src/scenarios.json with the picked scenarios + the raw work-item +// board so the UI can show a real "All work" view. +// +// READ-ONLY. Run: `node fetch_scenarios.mjs`. +import { writeFileSync } from "node:fs"; + +const BASE = process.env.FM_BASE || "https://demo.flow-master.ai"; +const EMAIL = process.env.FM_EMAIL || "dev@flow-master.ai"; + +const login = await fetch(`${BASE}/api/v1/auth/dev-login`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ email: EMAIL }), +}); +if (!login.ok) throw new Error(`dev-login ${login.status}`); +const token = (await login.json()).access_token; +const H = { Authorization: `Bearer ${token}` }; + +const tryGet = async (path) => { + try { + const r = await fetch(`${BASE}${path}`, { headers: H }); + if (!r.ok) return null; + return await r.json(); + } catch { + return null; + } +}; + +// 1. Pull the full live work-item board. +const board = await tryGet("/api/ea2/work-items?view=all"); +const workItems = board?.items || []; +console.log(`✓ ${workItems.length} live work-items`); + +// 2. Enumerate unique definition_keys + per-def metadata. +const byDef = new Map(); +for (const w of workItems) { + const k = w.definition_key; + if (!k) continue; + if (!byDef.has(k)) { + byDef.set(k, { key: k, hubs: new Set(), cases: [], statuses: {} }); + } + const r = byDef.get(k); + if (w.hub) r.hubs.add(w.hub); + r.cases.push(w); + r.statuses[w.status] = (r.statuses[w.status] || 0) + 1; +} +console.log(`✓ ${byDef.size} distinct definitions in work board`); + +// 3. Filter to meaningful definitions (≥1 running OR ≥2 total cases). +const candidates = [...byDef.values()].filter((d) => { + const total = d.cases.length; + const running = (d.statuses.running || 0) + (d.statuses.waiting_for_user || 0); + return total >= 2 || running >= 1; +}); +candidates.sort((a, b) => b.cases.length - a.cases.length); +console.log(`✓ ${candidates.length} candidates after filter`); + +// 4. Fetch graph + representative transaction per candidate. +const enriched = []; +for (const c of candidates.slice(0, 20)) { + const graph = await tryGet(`/api/ea2/process-definitions/${c.key}/graph`); + if (!graph?.process_definition?.config?.nodes?.length) { + console.warn(` ! ${c.key.slice(0, 8)} no graph`); + continue; + } + const headlineCase = + c.cases.find((w) => w.status === "running") || + c.cases.find((w) => w.status === "waiting_for_user") || + c.cases.find((w) => w.status === "errored" || w.status === "failed") || + c.cases[0]; + let headlineRt = null; + if (headlineCase?.transaction_id) { + headlineRt = await tryGet(`/api/runtime/transactions/${headlineCase.transaction_id}`); + } + const recent = []; + for (const w of c.cases.slice(0, 6)) { + if (!w.transaction_id || w.transaction_id === headlineCase?.transaction_id) continue; + const r = await tryGet(`/api/runtime/transactions/${w.transaction_id}`); + if (r) recent.push(r); + if (recent.length >= 3) break; + } + enriched.push({ + key: c.key, + name: graph.process_definition.display_name || graph.process_definition.name, + hubs: [...c.hubs], + statuses: c.statuses, + cases: c.cases, + graph, + headlineCase, + headlineRt, + recent, + }); + console.log( + ` ✓ ${c.key.slice(0, 8)} ${(graph.process_definition.display_name || "—").slice(0, 36)} nodes=${graph.process_definition.config.nodes.length} cases=${c.cases.length} rt=${headlineRt ? "live" : "no"}` + ); +} + +// 5. Classify into families. +const families = [ + { + id: "procurement", label: "Procurement to Pay", subtitle: "Requisition → PO → 3-way match", + accent: "#3b82f6", + match: (e) => /procure|purchas|pr_to_po|atlas|requisition|po\b/i.test(`${e.name} ${e.hubs.join(" ")}`), + }, + { + id: "ar", label: "Accounts Receivable", subtitle: "Refunds, credits & collections", + accent: "#10b981", + match: (e) => /refund|credit|collect|receivable|ar\b|invoice/i.test(e.name), + }, + { + id: "hcm", label: "People Operations", subtitle: "Onboard · Offboard · Leave", + accent: "#a855f7", + match: (e) => /onboard|offboard|hire|hcm|employee|leave|payroll|hr\b/i.test(e.name), + }, + { + id: "gl", label: "GL Close", subtitle: "Accruals, reconciliations, journals", + accent: "#f59e0b", + match: (e) => /close|ledger|journal|accrual|reconcil|gl\b/i.test(e.name), + }, + { + id: "service", label: "Service Operations", subtitle: "Tickets, incidents, support", + accent: "#ef4444", + match: (e) => /ticket|incident|support|service|case\b/i.test(e.name), + }, +]; + +const scenarios = []; +const used = new Set(); + +for (const fam of families) { + const pick = enriched + .filter((e) => !used.has(e.key) && fam.match(e)) + .sort((a, b) => b.cases.length - a.cases.length)[0]; + if (!pick) { + console.log(` ⚠ family ${fam.id} unmatched`); + continue; + } + used.add(pick.key); + scenarios.push({ family: fam, ...pick }); +} + +// Top up to at least 4 with largest remaining. +const remaining = enriched.filter((e) => !used.has(e.key)); +remaining.sort((a, b) => b.cases.length - a.cases.length); +while (scenarios.length < 4 && remaining.length) { + const e = remaining.shift(); + scenarios.push({ + family: { + id: `extra-${scenarios.length}`, + label: e.name || "Process", + subtitle: `${e.cases.length} live cases`, + accent: "#64748b", + match: () => false, + }, + ...e, + }); + used.add(e.key); +} + +console.log( + `\n→ ${scenarios.length} scenarios: ` + + scenarios.map((s) => `${s.family.id}:${s.name?.slice(0, 24)}`).join(" | ") +); + +// 6. Write artifact. +const out = { + fetchedFrom: BASE, + fetchedAt: new Date().toISOString(), + totals: { + workItems: workItems.length, + distinctDefs: byDef.size, + scenarios: scenarios.length, + }, + board: workItems, + scenarios: scenarios.map((s) => ({ + id: s.family.id, + family: s.family, + def_key: s.key, + def_name: s.name, + hubs: s.hubs, + statuses: s.statuses, + cases: s.cases, + graph: s.graph, + headlineTx: s.headlineCase?.transaction_id || null, + headlineRt: s.headlineRt, + recent: s.recent, + })), +}; +writeFileSync(new URL("./src/scenarios.json", import.meta.url), JSON.stringify(out, null, 2)); +console.log(`\n✓ wrote src/scenarios.json (${scenarios.length} scenarios, ${workItems.length} board items)`); diff --git a/index.html b/index.html new file mode 100644 index 0000000..a4ba5e4 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + fm-command-center-spike + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..f5e39fa --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "flowmaster-mission-control-demo", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview", + "test": "vitest run", + "test:watch": "vitest", + "fetch:scenarios": "node fetch_scenarios.mjs", + "qa:smoke": "node qa/smoke.mjs", + "qa:layout": "node qa/layout_audit.mjs" + }, + "dependencies": { + "@types/dagre": "^0.7.54", + "cmdk": "^1.1.1", + "dagre": "^0.8.5", + "framer-motion": "^12.40.0", + "react": "^19.2.6", + "react-dom": "^19.2.6", + "reactflow": "^11.11.4", + "zustand": "^5.0.14" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/node": "^24.12.3", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.1", + "eslint": "^10.3.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.2", + "globals": "^17.6.0", + "playwright": "^1.60.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.59.2", + "vite": "^8.0.12", + "vitest": "^4.1.8" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..d436620 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2998 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@types/dagre': + specifier: ^0.7.54 + version: 0.7.54 + cmdk: + specifier: ^1.1.1 + version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + dagre: + specifier: ^0.8.5 + version: 0.8.5 + framer-motion: + specifier: ^12.40.0 + version: 12.40.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: + specifier: ^19.2.6 + version: 19.2.7 + react-dom: + specifier: ^19.2.6 + version: 19.2.7(react@19.2.7) + reactflow: + specifier: ^11.11.4 + version: 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + zustand: + specifier: ^5.0.14 + version: 5.0.14(@types/react@19.2.17)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)) + devDependencies: + '@eslint/js': + specifier: ^10.0.1 + version: 10.0.1(eslint@10.5.0) + '@types/node': + specifier: ^24.12.3 + version: 24.13.2 + '@types/react': + specifier: ^19.2.14 + version: 19.2.17 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.17) + '@vitejs/plugin-react': + specifier: ^6.0.1 + version: 6.0.2(vite@8.0.16(@types/node@24.13.2)) + eslint: + specifier: ^10.3.0 + version: 10.5.0 + eslint-plugin-react-hooks: + specifier: ^7.1.1 + version: 7.1.1(eslint@10.5.0) + eslint-plugin-react-refresh: + specifier: ^0.5.2 + version: 0.5.2(eslint@10.5.0) + globals: + specifier: ^17.6.0 + version: 17.6.0 + playwright: + specifier: ^1.60.0 + version: 1.60.0 + typescript: + specifier: ~6.0.2 + version: 6.0.3 + typescript-eslint: + specifier: ^8.59.2 + version: 8.61.0(eslint@10.5.0)(typescript@6.0.3) + vite: + specifier: ^8.0.12 + version: 8.0.16(@types/node@24.13.2) + vitest: + specifier: ^4.1.8 + version: 4.1.8(@types/node@24.13.2)(vite@8.0.16(@types/node@24.13.2)) + +packages: + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/config-helpers@0.6.0': + resolution: {integrity: sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/js@10.0.1': + resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^10.0.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + + '@radix-ui/primitive@1.1.4': + resolution: {integrity: sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ==} + + '@radix-ui/react-compose-refs@1.1.3': + resolution: {integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.1.4': + resolution: {integrity: sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.16': + resolution: {integrity: sha512-l9ok83YBclEZhbjgzt76Hw733e6cvRKPNgO6GJ/IETlufXG9p+fRu2wlvpImQvR6xdJ8h7J8J2DBvsPEiEsKMw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.12': + resolution: {integrity: sha512-MhoruH6xEzsbvOmo4TNgMfmtvRGyDZw4MDSdf4ybMHfezjqwzv6hyd4lsMzBp8K9Sn6sGzCF62x1I7BYUECXOg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.4': + resolution: {integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.9': + resolution: {integrity: sha512-9Se8t+Zry+1rEOL7Y6l/4ANYU/TOtAtf8O2fKdwLltcaMcm6kOqYGbzO4tMFQ0bvzO920pRAoHpFZ4W85S3keQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.2': + resolution: {integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-portal@1.1.11': + resolution: {integrity: sha512-UEytdjgEh2tJGgD/gZK4FUx6t1rNIlM3U0DENhSrG7I75FGm1DnaDuVUWF1pWAWUwGmn1sCJ1VGHn8LhN1aTOw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.6': + resolution: {integrity: sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.1.5': + resolution: {integrity: sha512-zifXeB8Y88qCYx8PLZ5oQb32KwZub+s925mMoZsBBq9KUQqWKkREubTfs6ASjRPPBe7Jt9O8OHH89+95VG+grA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.2.5': + resolution: {integrity: sha512-rCMO3QsIVKv5JTY5CVbo2MvO77SpEqqYc8AvRE7OWqRDOIqAKjsp+DrmnY9uc8NPdxB5E2z47HTYGeE2+NTptg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.2': + resolution: {integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.3': + resolution: {integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.3': + resolution: {integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.2': + resolution: {integrity: sha512-2uVLvLjgO7NZCWw01/FdqRwmA42J0BcjPMUCA+koFEOAb+zjqIP7SiFz/7zWPrKnVmSqr76Omq2ALyCuX4dhLw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.2': + resolution: {integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@reactflow/background@11.3.14': + resolution: {integrity: sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/controls@11.2.14': + resolution: {integrity: sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/core@11.11.4': + resolution: {integrity: sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/minimap@11.7.14': + resolution: {integrity: sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/node-resizer@2.2.14': + resolution: {integrity: sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@reactflow/node-toolbar@1.3.14': + resolution: {integrity: sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} + + '@types/d3-axis@3.0.6': + resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} + + '@types/d3-brush@3.0.6': + resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} + + '@types/d3-chord@3.0.6': + resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-contour@3.0.6': + resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} + + '@types/d3-delaunay@6.0.4': + resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} + + '@types/d3-dispatch@3.0.7': + resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} + + '@types/d3-drag@3.0.7': + resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} + + '@types/d3-dsv@3.0.7': + resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-fetch@3.0.7': + resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} + + '@types/d3-force@3.0.10': + resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} + + '@types/d3-format@3.0.4': + resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} + + '@types/d3-geo@3.1.0': + resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} + + '@types/d3-hierarchy@3.1.7': + resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-polygon@3.0.2': + resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} + + '@types/d3-quadtree@3.0.6': + resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} + + '@types/d3-random@3.0.3': + resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} + + '@types/d3-scale-chromatic@3.1.0': + resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-selection@3.0.11': + resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} + + '@types/d3-shape@3.1.8': + resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} + + '@types/d3-time-format@4.0.3': + resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/d3-transition@3.0.9': + resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} + + '@types/d3-zoom@3.0.8': + resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} + + '@types/d3@7.4.3': + resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} + + '@types/dagre@0.7.54': + resolution: {integrity: sha512-QjcRY+adGbYvBFS7cwv5txhVIwX1XXIUswWl+kSQTbI6NjgZydrZkEKX/etzVd7i+bCsCb40Z/xlBY5eoFuvWQ==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/geojson@7946.0.16': + resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@24.13.2': + resolution: {integrity: sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.17': + resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + + '@typescript-eslint/eslint-plugin@8.61.0': + resolution: {integrity: sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.61.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.61.0': + resolution: {integrity: sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.61.0': + resolution: {integrity: sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.61.0': + resolution: {integrity: sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.61.0': + resolution: {integrity: sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.61.0': + resolution: {integrity: sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.61.0': + resolution: {integrity: sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.61.0': + resolution: {integrity: sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.61.0': + resolution: {integrity: sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.61.0': + resolution: {integrity: sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitejs/plugin-react@6.0.2': + resolution: {integrity: sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + + '@vitest/expect@4.1.8': + resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} + + '@vitest/mocker@4.1.8': + resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.8': + resolution: {integrity: sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==} + + '@vitest/runner@4.1.8': + resolution: {integrity: sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==} + + '@vitest/snapshot@4.1.8': + resolution: {integrity: sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==} + + '@vitest/spy@4.1.8': + resolution: {integrity: sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==} + + '@vitest/utils@4.1.8': + resolution: {integrity: sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.10.37: + resolution: {integrity: sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==} + engines: {node: '>=6.0.0'} + hasBin: true + + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} + + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + caniuse-lite@1.0.30001799: + resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + classcat@5.0.5: + resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==} + + cmdk@1.1.1: + resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} + peerDependencies: + react: ^18 || ^19 || ^19.0.0-rc + react-dom: ^18 || ^19 || ^19.0.0-rc + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + dagre@0.8.5: + resolution: {integrity: sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + electron-to-chromium@1.5.372: + resolution: {integrity: sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==} + + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 + + eslint-plugin-react-refresh@0.5.2: + resolution: {integrity: sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==} + peerDependencies: + eslint: ^9 || ^10 + + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.5.0: + resolution: {integrity: sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + + framer-motion@12.40.0: + resolution: {integrity: sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@17.6.0: + resolution: {integrity: sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==} + engines: {node: '>=18'} + + graphlib@2.1.8: + resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==} + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + motion-dom@12.40.0: + resolution: {integrity: sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg==} + + motion-utils@12.39.0: + resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.47: + resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} + engines: {node: '>=18'} + + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + engines: {node: '>=12.20.0'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + playwright-core@1.60.0: + resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.60.0: + resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} + engines: {node: '>=18'} + hasBin: true + + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + react-dom@19.2.7: + resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} + peerDependencies: + react: ^19.2.7 + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@19.2.7: + resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + engines: {node: '>=0.10.0'} + + reactflow@11.11.4: + resolution: {integrity: sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og==} + peerDependencies: + react: '>=17' + react-dom: '>=17' + + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.4: + resolution: {integrity: sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript-eslint@8.61.0: + resolution: {integrity: sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + vite@8.0.16: + resolution: {integrity: sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.8: + resolution: {integrity: sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.8 + '@vitest/browser-preview': 4.1.8 + '@vitest/browser-webdriverio': 4.1.8 + '@vitest/coverage-istanbul': 4.1.8 + '@vitest/coverage-v8': 4.1.8 + '@vitest/ui': 4.1.8 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + + zustand@4.5.7: + resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': '>=16.8' + immer: '>=9.0.6' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + + zustand@5.0.14: + resolution: {integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.7': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/traverse@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@10.5.0)': + dependencies: + eslint: 10.5.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.23.5': + dependencies: + '@eslint/object-schema': 3.0.5 + debug: 4.4.3 + minimatch: 10.2.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.6.0': + dependencies: + '@eslint/core': 1.2.1 + + '@eslint/core@1.2.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/js@10.0.1(eslint@10.5.0)': + optionalDependencies: + eslint: 10.5.0 + + '@eslint/object-schema@3.0.5': {} + + '@eslint/plugin-kit@0.7.2': + dependencies: + '@eslint/core': 1.2.1 + levn: 0.4.1 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true + + '@oxc-project/types@0.133.0': {} + + '@radix-ui/primitive@1.1.4': {} + + '@radix-ui/react-compose-refs@1.1.3(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-context@1.1.4(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-dialog@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.1.4(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-portal': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.2.5(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + aria-hidden: 1.2.6 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-dismissable-layer@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.4 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-escape-keydown': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-focus-guards@1.1.4(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-focus-scope@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-id@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-portal@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-primitive': 2.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-presence@1.1.6(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-primitive@2.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-slot': 1.2.5(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-slot@1.2.5(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-callback-ref@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-controllable-state@1.2.3(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-effect-event@0.0.3(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-escape-keydown@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-layout-effect@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@reactflow/background@11.3.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + classcat: 5.0.5 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/controls@11.2.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + classcat: 5.0.5 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/core@11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@types/d3': 7.4.3 + '@types/d3-drag': 3.0.7 + '@types/d3-selection': 3.0.11 + '@types/d3-zoom': 3.0.8 + classcat: 5.0.5 + d3-drag: 3.0.0 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/minimap@11.7.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@types/d3-selection': 3.0.11 + '@types/d3-zoom': 3.0.8 + classcat: 5.0.5 + d3-selection: 3.0.0 + d3-zoom: 3.0.0 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/node-resizer@2.2.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + classcat: 5.0.5 + d3-drag: 3.0.0 + d3-selection: 3.0.0 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + '@reactflow/node-toolbar@1.3.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@reactflow/core': 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + classcat: 5.0.5 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + zustand: 4.5.7(@types/react@19.2.17)(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + '@rolldown/binding-android-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.3': + optional: true + + '@rolldown/binding-darwin-x64@1.0.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.3': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.3': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@standard-schema/spec@1.1.0': {} + + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/d3-array@3.2.2': {} + + '@types/d3-axis@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-brush@3.0.6': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-chord@3.0.6': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-contour@3.0.6': + dependencies: + '@types/d3-array': 3.2.2 + '@types/geojson': 7946.0.16 + + '@types/d3-delaunay@6.0.4': {} + + '@types/d3-dispatch@3.0.7': {} + + '@types/d3-drag@3.0.7': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-dsv@3.0.7': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-fetch@3.0.7': + dependencies: + '@types/d3-dsv': 3.0.7 + + '@types/d3-force@3.0.10': {} + + '@types/d3-format@3.0.4': {} + + '@types/d3-geo@3.1.0': + dependencies: + '@types/geojson': 7946.0.16 + + '@types/d3-hierarchy@3.1.7': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-polygon@3.0.2': {} + + '@types/d3-quadtree@3.0.6': {} + + '@types/d3-random@3.0.3': {} + + '@types/d3-scale-chromatic@3.1.0': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-selection@3.0.11': {} + + '@types/d3-shape@3.1.8': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time-format@4.0.3': {} + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/d3-transition@3.0.9': + dependencies: + '@types/d3-selection': 3.0.11 + + '@types/d3-zoom@3.0.8': + dependencies: + '@types/d3-interpolate': 3.0.4 + '@types/d3-selection': 3.0.11 + + '@types/d3@7.4.3': + dependencies: + '@types/d3-array': 3.2.2 + '@types/d3-axis': 3.0.6 + '@types/d3-brush': 3.0.6 + '@types/d3-chord': 3.0.6 + '@types/d3-color': 3.1.3 + '@types/d3-contour': 3.0.6 + '@types/d3-delaunay': 6.0.4 + '@types/d3-dispatch': 3.0.7 + '@types/d3-drag': 3.0.7 + '@types/d3-dsv': 3.0.7 + '@types/d3-ease': 3.0.2 + '@types/d3-fetch': 3.0.7 + '@types/d3-force': 3.0.10 + '@types/d3-format': 3.0.4 + '@types/d3-geo': 3.1.0 + '@types/d3-hierarchy': 3.1.7 + '@types/d3-interpolate': 3.0.4 + '@types/d3-path': 3.1.1 + '@types/d3-polygon': 3.0.2 + '@types/d3-quadtree': 3.0.6 + '@types/d3-random': 3.0.3 + '@types/d3-scale': 4.0.9 + '@types/d3-scale-chromatic': 3.1.0 + '@types/d3-selection': 3.0.11 + '@types/d3-shape': 3.1.8 + '@types/d3-time': 3.0.4 + '@types/d3-time-format': 4.0.3 + '@types/d3-timer': 3.0.2 + '@types/d3-transition': 3.0.9 + '@types/d3-zoom': 3.0.8 + + '@types/dagre@0.7.54': {} + + '@types/deep-eql@4.0.2': {} + + '@types/esrecurse@4.3.1': {} + + '@types/estree@1.0.9': {} + + '@types/geojson@7946.0.16': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@24.13.2': + dependencies: + undici-types: 7.18.2 + + '@types/react-dom@19.2.3(@types/react@19.2.17)': + dependencies: + '@types/react': 19.2.17 + + '@types/react@19.2.17': + dependencies: + csstype: 3.2.3 + + '@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.5.0)(typescript@6.0.3))(eslint@10.5.0)(typescript@6.0.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.61.0(eslint@10.5.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.61.0 + '@typescript-eslint/type-utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.61.0 + eslint: 10.5.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.61.0(eslint@10.5.0)(typescript@6.0.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.61.0 + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.61.0 + debug: 4.4.3 + eslint: 10.5.0 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.61.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@6.0.3) + '@typescript-eslint/types': 8.61.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.61.0': + dependencies: + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/visitor-keys': 8.61.0 + + '@typescript-eslint/tsconfig-utils@8.61.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.61.0(eslint@10.5.0)(typescript@6.0.3)': + dependencies: + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3) + debug: 4.4.3 + eslint: 10.5.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.61.0': {} + + '@typescript-eslint/typescript-estree@8.61.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.61.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@6.0.3) + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/visitor-keys': 8.61.0 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.8.4 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.61.0(eslint@10.5.0)(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0) + '@typescript-eslint/scope-manager': 8.61.0 + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3) + eslint: 10.5.0 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.61.0': + dependencies: + '@typescript-eslint/types': 8.61.0 + eslint-visitor-keys: 5.0.1 + + '@vitejs/plugin-react@6.0.2(vite@8.0.16(@types/node@24.13.2))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.0.16(@types/node@24.13.2) + + '@vitest/expect@4.1.8': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.8(vite@8.0.16(@types/node@24.13.2))': + dependencies: + '@vitest/spy': 4.1.8 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.16(@types/node@24.13.2) + + '@vitest/pretty-format@4.1.8': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.8': + dependencies: + '@vitest/utils': 4.1.8 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.8': + dependencies: + '@vitest/pretty-format': 4.1.8 + '@vitest/utils': 4.1.8 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.8': {} + + '@vitest/utils@4.1.8': + dependencies: + '@vitest/pretty-format': 4.1.8 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + acorn-jsx@5.3.2(acorn@8.17.0): + dependencies: + acorn: 8.17.0 + + acorn@8.17.0: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + assertion-error@2.0.1: {} + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.10.37: {} + + brace-expansion@5.0.6: + dependencies: + balanced-match: 4.0.4 + + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.37 + caniuse-lite: 1.0.30001799 + electron-to-chromium: 1.5.372 + node-releases: 2.0.47 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + + caniuse-lite@1.0.30001799: {} + + chai@6.2.2: {} + + classcat@5.0.5: {} + + cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dialog': 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.5(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + d3-color@3.1.0: {} + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-ease@3.0.1: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-selection@3.0.0: {} + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + dagre@0.8.5: + dependencies: + graphlib: 2.1.8 + lodash: 4.18.1 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + detect-libc@2.1.2: {} + + detect-node-es@1.1.0: {} + + electron-to-chromium@1.5.372: {} + + es-module-lexer@2.1.0: {} + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-plugin-react-hooks@7.1.1(eslint@10.5.0): + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.7 + eslint: 10.5.0 + hermes-parser: 0.25.1 + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-refresh@0.5.2(eslint@10.5.0): + dependencies: + eslint: 10.5.0 + + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@10.5.0: + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@10.5.0) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.6.0 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.2 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + minimatch: 10.2.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@11.2.0: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + eslint-visitor-keys: 5.0.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + esutils@2.0.3: {} + + expect-type@1.3.0: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flatted@3.4.2: {} + + framer-motion@12.40.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + motion-dom: 12.40.0 + motion-utils: 12.39.0 + tslib: 2.8.1 + optionalDependencies: + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + gensync@1.0.0-beta.2: {} + + get-nonce@1.0.1: {} + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@17.6.0: {} + + graphlib@2.1.8: + dependencies: + lodash: 4.18.1 + + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + imurmurhash@0.1.4: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + isexe@2.0.0: {} + + js-tokens@4.0.0: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash@4.18.1: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.6 + + motion-dom@12.40.0: + dependencies: + motion-utils: 12.39.0 + + motion-utils@12.39.0: {} + + ms@2.1.3: {} + + nanoid@3.3.12: {} + + natural-compare@1.4.0: {} + + node-releases@2.0.47: {} + + obug@2.1.3: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.4: {} + + playwright-core@1.60.0: {} + + playwright@1.60.0: + dependencies: + playwright-core: 1.60.0 + optionalDependencies: + fsevents: 2.3.2 + + postcss@8.5.15: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + punycode@2.3.1: {} + + react-dom@19.2.7(react@19.2.7): + dependencies: + react: 19.2.7 + scheduler: 0.27.0 + + react-remove-scroll-bar@2.3.8(@types/react@19.2.17)(react@19.2.7): + dependencies: + react: 19.2.7 + react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + react-remove-scroll@2.7.2(@types/react@19.2.17)(react@19.2.7): + dependencies: + react: 19.2.7 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.17)(react@19.2.7) + react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.2.17)(react@19.2.7) + use-sidecar: 1.1.3(@types/react@19.2.17)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + + react-style-singleton@2.2.3(@types/react@19.2.17)(react@19.2.7): + dependencies: + get-nonce: 1.0.1 + react: 19.2.7 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + react@19.2.7: {} + + reactflow@11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + '@reactflow/background': 11.3.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@reactflow/controls': 11.2.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@reactflow/core': 11.11.4(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@reactflow/minimap': 11.7.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@reactflow/node-resizer': 2.2.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@reactflow/node-toolbar': 1.3.14(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + transitivePeerDependencies: + - '@types/react' + - immer + + rolldown@1.0.3: + dependencies: + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + semver@7.8.4: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@4.1.0: {} + + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyrainbow@3.1.0: {} + + ts-api-utils@2.5.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + + tslib@2.8.1: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript-eslint@8.61.0(eslint@10.5.0)(typescript@6.0.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.61.0(@typescript-eslint/parser@8.61.0(eslint@10.5.0)(typescript@6.0.3))(eslint@10.5.0)(typescript@6.0.3) + '@typescript-eslint/parser': 8.61.0(eslint@10.5.0)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.61.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.61.0(eslint@10.5.0)(typescript@6.0.3) + eslint: 10.5.0 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + typescript@6.0.3: {} + + undici-types@7.18.2: {} + + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-callback-ref@1.3.3(@types/react@19.2.17)(react@19.2.7): + dependencies: + react: 19.2.7 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + use-sidecar@1.1.3(@types/react@19.2.17)(react@19.2.7): + dependencies: + detect-node-es: 1.1.0 + react: 19.2.7 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + use-sync-external-store@1.6.0(react@19.2.7): + dependencies: + react: 19.2.7 + + vite@8.0.16(@types/node@24.13.2): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.0.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.2 + fsevents: 2.3.3 + + vitest@4.1.8(@types/node@24.13.2)(vite@8.0.16(@types/node@24.13.2)): + dependencies: + '@vitest/expect': 4.1.8 + '@vitest/mocker': 4.1.8(vite@8.0.16(@types/node@24.13.2)) + '@vitest/pretty-format': 4.1.8 + '@vitest/runner': 4.1.8 + '@vitest/snapshot': 4.1.8 + '@vitest/spy': 4.1.8 + '@vitest/utils': 4.1.8 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.3 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.0.16(@types/node@24.13.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.13.2 + transitivePeerDependencies: + - msw + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + zod-validation-error@4.0.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + + zod@4.4.3: {} + + zustand@4.5.7(@types/react@19.2.17)(react@19.2.7): + dependencies: + use-sync-external-store: 1.6.0(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + react: 19.2.7 + + zustand@5.0.14(@types/react@19.2.17)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)): + optionalDependencies: + '@types/react': 19.2.17 + react: 19.2.7 + use-sync-external-store: 1.6.0(react@19.2.7) diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons.svg b/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/qa/layout_audit.mjs b/qa/layout_audit.mjs new file mode 100644 index 0000000..4d00fdf --- /dev/null +++ b/qa/layout_audit.mjs @@ -0,0 +1,93 @@ +// Programmatic visual-QA: walks the rendered DOM and reports likely +// layout defects (overflow, clipping, overlap, zero-size, low contrast). +import { chromium } from "playwright"; + +const URL = process.env.URL || "http://127.0.0.1:5173"; +const browser = await chromium.launch({ headless: true }); +const page = await browser.newPage({ viewport: { width: 1440, height: 900 } }); + +const findings = []; +function add(kind, msg) { findings.push({ kind, msg }); } + +await page.goto(URL, { waitUntil: "networkidle" }); + +async function auditScene(label, prep) { + await prep(); + await page.waitForTimeout(500); + // For each candidate selector, check for overflow / hidden / zero size + const results = await page.evaluate(() => { + const out = []; + const sels = [ + ".hero-title", ".hero-sub", ".sc-card-title", ".sc-card-sub", + ".mc-hero-title", ".mc-hero-sub", ".mc-tab-label", + ".node-name", ".panel-h", ".qcard-title", ".inspector-title h3", + ".tour-title", ".tour-body", ".telemetry .t-block", ".rh-row-step", + ".graph-overlay-name", + ]; + for (const sel of sels) { + for (const el of Array.from(document.querySelectorAll(sel))) { + const r = el.getBoundingClientRect(); + const cs = getComputedStyle(el); + const clipped = el.scrollWidth > r.width + 1 && cs.overflow !== "visible" && cs.textOverflow === "ellipsis"; + const overflowH = el.scrollHeight > r.height + 1 && cs.overflow !== "visible" && cs.overflowY !== "auto" && cs.overflowY !== "scroll"; + const offscreen = r.right < 0 || r.left > window.innerWidth || r.bottom < 0 || r.top > window.innerHeight + 1; + const zero = (r.width < 2 || r.height < 2) && el.textContent && el.textContent.trim().length > 0; + if (clipped || overflowH || offscreen || zero) { + out.push({ + sel, text: (el.textContent || "").trim().slice(0, 80), + w: r.width.toFixed(0), h: r.height.toFixed(0), + sw: el.scrollWidth, sh: el.scrollHeight, + issues: { clipped, overflowH, offscreen, zero }, + }); + } + } + } + return out; + }); + for (const r of results) { + add("layout", `[${label}] ${r.sel}: "${r.text}" (${r.w}x${r.h} content ${r.sw}x${r.sh}) ${JSON.stringify(r.issues)}`); + } +} + +await auditScene("landing", async () => {}); +await auditScene("mission-1st-live", async () => { + await page.locator(".sc-card").first().click(); + await page.waitForSelector(".mc"); +}); +await auditScene("mission-ar", async () => { + await page.locator(".mc-tab", { hasText: "Accounts Receivable" }).click(); +}); +await auditScene("inspector-raw", async () => { + await page.locator(".itab", { hasText: "Raw" }).click(); +}); +await auditScene("tour", async () => { + await page.locator(".link-btn", { hasText: "Tour" }).click(); + await page.waitForSelector(".tour-card"); +}); +await auditScene("history", async () => { + await page.keyboard.press("Escape"); + await page.waitForTimeout(100); + await page.locator(".tab", { hasText: "Runs" }).click(); + await page.waitForSelector(".rh"); +}); + +console.log(`findings: ${findings.length}`); +for (const f of findings.slice(0, 50)) console.log(` · ${f.msg}`); + +// Also dump key layout dimensions for sanity +const dims = await page.evaluate(() => { + const get = (sel) => { + const el = document.querySelector(sel); + if (!el) return null; + const r = el.getBoundingClientRect(); + return { sel, w: Math.round(r.width), h: Math.round(r.height), top: Math.round(r.top), left: Math.round(r.left) }; + }; + return [ + get(".rh-head"), + get(".rh-list"), + get(".rh-row"), + ]; +}); +console.log("\nrh dimensions:", JSON.stringify(dims, null, 2)); + +await browser.close(); diff --git a/qa/smoke.mjs b/qa/smoke.mjs new file mode 100644 index 0000000..c01ba23 --- /dev/null +++ b/qa/smoke.mjs @@ -0,0 +1,155 @@ +// Playwright smoke + screenshot capture against the running dev server. +// Covers: landing, MC procurement, MC blueprint (AR), inspector tabs, +// command palette, tour, run history, live-mode toggle, toast on preview action. +import { chromium } from "playwright"; +import { mkdirSync } from "node:fs"; + +const URL = process.env.URL || "http://127.0.0.1:5173"; +const OUT = "qa/screenshots"; +mkdirSync(OUT, { recursive: true }); + +const VP = { width: 1440, height: 900 }; + +function logOk(label, ok, detail = "") { + console.log(`${ok ? "✓" : "✗"} ${label}${detail ? " · " + detail : ""}`); + if (!ok) process.exitCode = 1; +} + +const browser = await chromium.launch({ headless: true }); +const ctx = await browser.newContext({ viewport: VP, deviceScaleFactor: 1 }); +const page = await ctx.newPage(); + +const errors = []; +page.on("pageerror", (e) => errors.push(`pageerror: ${e.message}`)); +page.on("console", (m) => { if (m.type() === "error") errors.push(`console.error: ${m.text()}`); }); + +await page.goto(URL, { waitUntil: "networkidle" }); +await page.waitForTimeout(400); +await page.screenshot({ path: `${OUT}/01-landing.png` }); +logOk("landing renders", await page.locator(".landing").isVisible()); +logOk("hero title present", await page.locator(".hero-title").isVisible()); +const cards = await page.locator(".sc-card").count(); +logOk("scenario cards >= 7", cards >= 7, `count=${cards}`); +logOk("Go live button visible on landing", await page.getByRole("button", { name: /go live/i }).isVisible()); + +// → Mission Control via first card (live procurement) +await page.locator(".sc-card").first().click(); +await page.waitForSelector(".mc"); +await page.waitForTimeout(600); +await page.screenshot({ path: `${OUT}/02-mission-procurement.png` }); +logOk("mission control loaded", await page.locator(".mc-strip").isVisible()); + +// Topbar mode pill is SNAPSHOT by default +const modeBefore = (await page.locator(".mode-toggle .mode-pill").innerText()).trim(); +logOk("default mode is SNAPSHOT", modeBefore === "SNAPSHOT", `was=${modeBefore}`); + +// Tab strip + graph +const tabCount = await page.locator(".mc-tab").count(); +logOk("tab strip has >= 7 scenarios", tabCount >= 7, `count=${tabCount}`); +const reactFlowNodes = await page.locator(".node").count(); +logOk("graph rendered nodes > 0", reactFlowNodes > 0, `nodes=${reactFlowNodes}`); + +// Switch to AR blueprint +await page.locator(".mc-tab", { hasText: "Accounts Receivable" }).click(); +await page.waitForTimeout(600); +await page.screenshot({ path: `${OUT}/03-mission-ar.png` }); +logOk("AR scenario active", (await page.locator(".mc-hero-title").innerText()).toLowerCase().includes("refund")); +logOk("AR shows BLUEPRINT badge (not SYNTHETIC)", await page.locator(".graph-overlay .tag-syn", { hasText: "BLUEPRINT" }).isVisible()); + +// Queue card → inspector update +const qCards = await page.locator(".qcard").count(); +logOk("queue cards present", qCards > 0, `count=${qCards}`); +if (qCards > 0) { + await page.locator(".qcard").first().click(); + await page.waitForTimeout(200); +} + +// Inspector tab switching +await page.locator(".itab", { hasText: "Evidence" }).click(); +await page.waitForTimeout(150); +logOk("evidence tab opens", await page.locator(".evt, .empty").first().isVisible()); +await page.locator(".itab", { hasText: "Raw" }).click(); +await page.waitForTimeout(150); +logOk("raw tab opens", await page.locator(".raw-json").isVisible()); +await page.screenshot({ path: `${OUT}/04-inspector-raw.png` }); + +// Preview-only action toast +await page.locator(".itab", { hasText: "Overview" }).click(); +await page.waitForTimeout(150); +const approveBtn = page.locator(".i-actions .btn", { hasText: "Approve" }).first(); +const approveCount = await approveBtn.count(); +if (approveCount > 0) { + await approveBtn.click(); + await page.waitForTimeout(300); + const toastTxt = (await page.locator(".toast-msg").first().innerText()).trim(); + logOk("preview action fires toast", /preview[- ]only/i.test(toastTxt), `toast="${toastTxt.slice(0, 80)}"`); +} else { + logOk("approve button preview-marker present", await page.locator(".preview-marker").first().isVisible()); +} + +// Command palette +await page.keyboard.press("Meta+k"); +await page.waitForSelector(".cmd", { state: "visible" }); +await page.waitForTimeout(150); +await page.screenshot({ path: `${OUT}/05-command-palette.png` }); +logOk("command palette opens with ⌘K", await page.locator(".cmd").isVisible()); +logOk("Data mode group present in palette", await page.locator(".cmd").getByText(/data mode/i).isVisible()); + +await page.locator('.cmd [cmdk-input]').fill("tour"); +await page.waitForTimeout(150); +logOk("tour command appears", await page.locator(".cmd").getByText(/start guided tour/i).isVisible()); +await page.keyboard.press("Escape"); +await page.waitForTimeout(100); + +// Start tour +await page.locator(".link-btn", { hasText: "Tour" }).click(); +await page.waitForSelector(".tour-card"); +await page.waitForTimeout(250); +await page.screenshot({ path: `${OUT}/06-tour.png` }); +logOk("tour card renders", await page.locator(".tour-card").isVisible()); +const firstTourCombined = ((await page.locator(".tour-title").first().innerText()) + " " + (await page.locator(".tour-body").first().innerText())).toLowerCase(); +logOk("AR tour uses positive 'industry blueprint' framing", /industry blueprint/i.test(firstTourCombined), `text~="${firstTourCombined.slice(0, 100)}"`); +await page.keyboard.press("ArrowRight"); +await page.waitForTimeout(450); +logOk("tour advances", (await page.locator(".tour-title").first().innerText()).length > 0); +await page.keyboard.press("Escape"); + +// Live-mode toggle (real network call to demo.flow-master.ai) +const toggleBtn = page.locator(".mode-toggle").first(); +await toggleBtn.click(); +const liveOk = await page.waitForFunction( + () => Array.from(document.querySelectorAll(".mode-pill")).some((el) => el.textContent?.trim() === "LIVE"), + { timeout: 12000 }, +).then(() => true).catch(() => false); +logOk("toggle to LIVE mode resolves and updates pill", liveOk); +if (liveOk) { + await page.waitForTimeout(400); + await page.screenshot({ path: `${OUT}/09-live-mode.png` }); + logOk("Refresh button appears in live mode", await page.locator(".link-btn", { hasText: "Refresh" }).isVisible()); +} + +// Telemetry honesty (check before leaving MC because RH has no telemetry strip) +const tel = await page.locator(".telemetry").innerText(); +logOk("telemetry has no hardcoded 97.4%", !/97\.4%/.test(tel), `tel="${tel.replace(/\s+/g, " ").slice(0, 80)}"`); +logOk("telemetry labels SLA as derived", /derived/i.test(tel)); + +// Run history scene +await page.locator(".tab", { hasText: "Runs" }).click(); +await page.waitForSelector(".rh"); +await page.waitForTimeout(250); +await page.screenshot({ path: `${OUT}/07-run-history.png` }); +const rhRows = await page.locator(".rh-row").count(); +logOk("run-history rows present", rhRows > 0, `rows=${rhRows}`); +await page.locator(".rh-chip", { hasText: "running" }).click(); +await page.waitForTimeout(200); +const rhRunning = await page.locator(".rh-row").count(); +logOk("run-history filter shrinks list", rhRunning > 0 && rhRunning <= rhRows, `running=${rhRunning} of ${rhRows}`); + +console.log(`\nconsole errors: ${errors.length}`); +for (const e of errors.slice(0, 8)) console.log(" -", e); +if (errors.length > 0) process.exitCode = 1; + +await browser.close(); +const fs = await import("node:fs/promises"); +const list = await fs.readdir(OUT); +console.log(`\n→ ${OUT}/ has ${list.length} screenshots: ${list.sort().join(", ")}`); diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..762b057 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,108 @@ +// App shell — scene switcher + top bar + command palette + tour overlay. +import { useApp, scenarioById } from "./state/store"; +import Landing from "./scenes/Landing"; +import MissionControl from "./scenes/MissionControl"; +import RunHistory from "./scenes/RunHistory"; +import CommandBar from "./components/CommandBar"; +import Tour from "./components/Tour"; +import Toaster from "./components/Toaster"; +import { Cmd, Home, Layers, History as HistoryIcon, Sparkles, Pulse, Refresh } from "./components/icons"; +import { liveMeta } from "./data/scenarios"; + +export default function App() { + const scene = useApp((s) => s.scene); + const setScene = useApp((s) => s.setScene); + const setCmdOpen = useApp((s) => s.setCmdOpen); + const scenarioId = useApp((s) => s.scenarioId); + const sc = scenarioById(scenarioId); + const startTour = useApp((s) => s.startTour); + const tourActive = useApp((s) => s.tour.active); + const mode = useApp((s) => s.mode); + const setMode = useApp((s) => s.setMode); + const liveLoading = useApp((s) => s.liveLoading); + const liveFetchedAt = useApp((s) => s.liveFetchedAt); + + const liveAge = liveFetchedAt ? `${Math.max(0, Math.floor((Date.now() - liveFetchedAt) / 1000))}s ago` : null; + + return ( +
+ {scene !== "landing" && ( +
+ + + + +
+ {sc && ( +
+ + {sc.family.label} + + + {sc.defName.slice(0, 40)} + + {sc.version} + {sc.live ? ( + live · {liveMeta.fetchedFrom?.replace("https://", "")} + ) : ( + blueprint + )} +
+ )} +
+ +
+ + {mode === "live" && ( + + )} + + +
+
+ )} + +
+ {scene === "landing" && } + {scene === "mission" && } + {scene === "history" && } +
+ + + + +
+ ); +} diff --git a/src/assets/hero.png b/src/assets/hero.png new file mode 100644 index 0000000..02251f4 Binary files /dev/null and b/src/assets/hero.png differ diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/vite.svg b/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/src/components/CommandBar.tsx b/src/components/CommandBar.tsx new file mode 100644 index 0000000..f5d4f34 --- /dev/null +++ b/src/components/CommandBar.tsx @@ -0,0 +1,140 @@ +// Command palette v2 — scenarios, steps, tour, scenes, recents. +import { useEffect, useMemo } from "react"; +import { Command } from "cmdk"; +import { useApp, scenarioById } from "../state/store"; +import { Play, Branch, Bot, Check, Sparkles, Home, History as HistoryIcon, Layers, Search, Refresh } from "./icons"; + +export default function CommandBar() { + const open = useApp((s) => s.cmdOpen); + const setOpen = useApp((s) => s.setCmdOpen); + const setScenarioId = useApp((s) => s.setScenarioId); + const setSelectedStepId = useApp((s) => s.setSelectedStepId); + const startTour = useApp((s) => s.startTour); + const setScene = useApp((s) => s.setScene); + const recents = useApp((s) => s.recents); + const scenarioId = useApp((s) => s.scenarioId); + const pushRecent = useApp((s) => s.pushRecent); + const scenarios = useApp((s) => s.scenarios); + const mode = useApp((s) => s.mode); + const setMode = useApp((s) => s.setMode); + const pushToast = useApp((s) => s.pushToast); + + const sc = scenarioById(scenarioId); + + const previewAction = (label: string) => { + pushToast("info", `${label} is preview-only in this demo. Wire to /api/runtime/transactions to make it real.`); + }; + + useEffect(() => { + const onKey = (e: KeyboardEvent) => { + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { + e.preventDefault(); + setOpen(!open); + } + if (e.key === "Escape" && open) setOpen(false); + }; + document.addEventListener("keydown", onKey); + return () => document.removeEventListener("keydown", onKey); + }, [open, setOpen]); + + const stepItems = useMemo(() => sc?.steps ?? [], [sc]); + + if (!open) return null; + + const close = () => setOpen(false); + + return ( +
+ e.stopPropagation()} label="Command bar"> +
+ + + esc +
+ + No matches. + + {recents.length > 0 && ( + + {recents.map((r, i) => ( + { pushRecent(r); close(); }}> + {r} + + ))} + + )} + + + { setScene("landing"); close(); }}> + Landing + + { setScene("mission"); close(); }}> + Mission Control + + { setScene("history"); close(); }}> + Run History + + + + + { startTour(); close(); }}> + Start guided tour presenter mode + + + + + {scenarios.map((s) => ( + { setScenarioId(s.id); setScene("mission"); close(); }} + > + + {s.family.label} + {s.live ? "live" : "blueprint"} · {s.defName} + + ))} + + + {sc && ( + + {stepItems.map((st) => ( + { setSelectedStepId(st.id); setScene("mission"); close(); }} + > + {st.name} + {st.kind} + + ))} + + )} + + + { setMode("live"); close(); }}> + {mode === "live" ? "Refresh live scenarios" : "Switch to LIVE mode (fetch demo.flow-master.ai)"} + {mode === "live" ? "re-fetch" : "in-browser"} + + { setMode("snapshot"); close(); }}> + Switch to SNAPSHOT mode + bundled JSON + + + + + { previewAction("Start runtime instance"); close(); }}> + Start runtime instance preview + + { previewAction("Dispatch sidekick agent"); close(); }}> + Dispatch sidekick agent preview + + { previewAction("Confirm awaiting agent runs"); close(); }}> + Confirm awaiting agent runs {sc?.agentRuns.length ?? 0} pending · preview + + + +
+
+ ); +} diff --git a/src/components/Inspector.tsx b/src/components/Inspector.tsx new file mode 100644 index 0000000..419ebb9 --- /dev/null +++ b/src/components/Inspector.tsx @@ -0,0 +1,173 @@ +// Tabbed Inspector for the selected step. +import { useMemo } from "react"; +import { useApp, scenarioById } from "../state/store"; +import { Shield, Doc, Layers, Pulse, History } from "./icons"; + +const STATE_LABEL: Record = { + done: "Done", running: "Running", queued: "Queued", + blocked: "Blocked", idle: "Idle", errored: "Errored", +}; + +const TABS: Array<{ id: "overview" | "rules" | "evidence" | "raw" | "runs"; label: string; Icon: typeof Doc }> = [ + { id: "overview", label: "Overview", Icon: Doc }, + { id: "rules", label: "Rules", Icon: Shield }, + { id: "evidence", label: "Evidence", Icon: Pulse }, + { id: "runs", label: "Runs", Icon: History }, + { id: "raw", label: "Raw", Icon: Layers }, +]; + +export default function Inspector() { + const scenarioId = useApp((s) => s.scenarioId); + const selectedStepId = useApp((s) => s.selectedStepId); + const tab = useApp((s) => s.inspectorTab); + const setTab = useApp((s) => s.setInspectorTab); + + const sc = scenarioById(scenarioId); + const step = useMemo( + () => (sc && selectedStepId ? sc.steps.find((s) => s.id === selectedStepId) ?? null : null), + [sc, selectedStepId], + ); + if (!sc) return null; + + return ( +
+
+
+ Inspector +

{step?.name ?? sc.defName}

+ {step && ( +
+ {step.kind} · {step.owner} · {STATE_LABEL[step.state]} +
+ )} +
+ +
+ +
+ {tab === "overview" && step && } + {tab === "overview" && !step && } + {tab === "rules" && step && } + {tab === "rules" && !step && } + {tab === "evidence" && step && } + {tab === "evidence" && !step && } + {tab === "runs" && } + {tab === "raw" && } +
+
+ ); +} + +function Empty({ msg }: { msg: string }) { + return
{msg}
; +} + +function PreviewActionButton({ kind, label }: { kind: "complete" | "approve" | "decline" | "fork"; label: string }) { + const pushToast = useApp((s) => s.pushToast); + const cls = kind === "approve" ? "btn btn-primary" : kind === "decline" ? "btn btn-ghost btn-decline" : "btn btn-ghost"; + return ( + + ); +} + +function OverviewTab({ step, sc }: { step: import("../data/types").ProcessStep; sc: import("../data/types").ProcessScenario }) { + return ( +
+
Step ID{step.id}
+
Kind{step.kind}
+
Owner{step.owner}
+
State{STATE_LABEL[step.state]}
+
Governs{step.governs.length ? step.governs.join(", ") : "—"}
+
Process{sc.defName} · {sc.version}
+ {step.actions.length > 0 && ( + <> +

Available actions preview

+
+ {step.actions.map((a: import("../data/types").StepAction) => ( + + ))} +
+ + )} +
+ ); +} + +function RulesTab({ step, sc }: { step: import("../data/types").ProcessStep; sc: import("../data/types").ProcessScenario }) { + const ruleIds = new Set(step.governs); + const rules = sc.rules.filter((r) => ruleIds.has(r.id)); + if (rules.length === 0) return ; + return ( +
+ {rules.map((r) => ( +
+
+ + {r.name} + {r.isSynthetic && blueprint} +
+
{r.expr}
+
+ ))} +
+ ); +} + +function EvidenceTab({ stepId, sc }: { stepId: string; sc: import("../data/types").ProcessScenario }) { + const items = sc.evidence.filter((e) => e.stepId === stepId); + if (items.length === 0) return ; + return ( +
+ {items.map((e) => ( +
+ {e.at} +
+ {e.actor}{e.isSynthetic ? " · synthetic" : ""} +
{e.summary}
+
+
+ ))} +
+ ); +} + +function RunsTab({ sc }: { sc: import("../data/types").ProcessScenario }) { + if (sc.runs.length === 0) return ; + return ( +
+ {sc.runs.map((r) => ( +
+
+ {r.shortId} + {r.status} + {r.activeStep ?? "—"} +
+
{r.startedAt?.slice(0, 16) || "—"} · {Math.round(r.durationSec / 60)}m
+
+ ))} +
+ ); +} + +function RawTab({ raw }: { raw: unknown }) { + const text = useMemo(() => JSON.stringify(raw ?? {}, null, 2), [raw]); + return
{text}
; +} diff --git a/src/components/LeftRail.tsx b/src/components/LeftRail.tsx new file mode 100644 index 0000000..60f0c67 --- /dev/null +++ b/src/components/LeftRail.tsx @@ -0,0 +1,97 @@ +// LeftRail: queues + agent runs for the active scenario. +import { useApp, scenarioById } from "../state/store"; +import { Inbox, Bot, Clock, Check, Close, ArrowUp, ArrowDown, Pulse } from "./icons"; + +const WAIT_LABEL: Record = { approval: "Approval", agent: "Agent", input: "Input" }; + +export default function LeftRail() { + const scenarioId = useApp((s) => s.scenarioId); + const setSelectedStepId = useApp((s) => s.setSelectedStepId); + const selectedStepId = useApp((s) => s.selectedStepId); + const sc = scenarioById(scenarioId); + if (!sc) return null; + + return ( + + ); +} diff --git a/src/components/ProcessGraph.tsx b/src/components/ProcessGraph.tsx new file mode 100644 index 0000000..fe40355 --- /dev/null +++ b/src/components/ProcessGraph.tsx @@ -0,0 +1,152 @@ +// Cinematic process graph. dagre auto-layout, animated active edge, +// glass nodes, minimap, selection ring. +import { useMemo, type ReactElement } from "react"; +import ReactFlow, { + Background, Controls, MiniMap, Handle, Position, + type Edge, type Node, type NodeProps, +} from "reactflow"; +import { useApp, scenarioById } from "../state/store"; +import { layoutGraph, NODE_SIZE } from "../graph/layout"; +import { Bot, User, Cog, Shield, Flag } from "./icons"; +import type { ProcessStep, StepKind } from "../data/types"; + +type NodeData = ProcessStep & { selected: boolean }; + +const KIND_ICON: Record ReactElement> = { + start: Flag, + end: Flag, + human: User, + agent: Bot, + service: Cog, + decision: Cog, +}; + +function StepNode({ data, id }: NodeProps) { + const Icon = KIND_ICON[data.kind] ?? Cog; + return ( +
+ +
+ + + {data.name} +
+
+ {data.kind} + {data.owner} + {data.governs.length > 0 && ( + {data.governs.length} + )} +
+ +
+ ); +} + +const nodeTypes = { step: StepNode }; + +const EDGE_COLOR: Record = { + done: "var(--ok)", + running: "var(--run)", + errored: "var(--block)", + default: "var(--border-strong)", +}; + +export default function ProcessGraph() { + const scenarioId = useApp((s) => s.scenarioId); + const selectedStepId = useApp((s) => s.selectedStepId); + const setSelectedStepId = useApp((s) => s.setSelectedStepId); + + const sc = scenarioById(scenarioId); + + const { nodes, edges } = useMemo(() => { + if (!sc) return { nodes: [] as Node[], edges: [] as Edge[] }; + const positions = layoutGraph(sc.steps, sc.edges); + const posById = new Map(positions.map((p) => [p.id, p.position])); + const stepById = new Map(sc.steps.map((s) => [s.id, s])); + const nodes: Node[] = sc.steps.map((s) => ({ + id: s.id, + type: "step", + position: posById.get(s.id) ?? { x: 0, y: 0 }, + data: { ...s, selected: s.id === selectedStepId }, + })); + const edges: Edge[] = sc.edges.map((e) => { + const srcStep = stepById.get(e.source); + const isRunningEdge = srcStep?.state === "running"; + const color = + srcStep?.state === "errored" + ? EDGE_COLOR.errored + : srcStep?.state === "done" + ? EDGE_COLOR.done + : srcStep?.state === "running" + ? EDGE_COLOR.running + : EDGE_COLOR.default; + return { + id: e.id, + source: e.source, + target: e.target, + label: e.label, + animated: isRunningEdge, + type: "smoothstep", + style: { stroke: color, strokeWidth: isRunningEdge ? 2.2 : 1.6, opacity: srcStep?.state === "idle" ? 0.55 : 1 }, + labelStyle: { fill: "var(--text-2)", fontSize: 11, fontFamily: "Fira Sans", fontWeight: 500 }, + labelBgPadding: [6, 4], + labelBgBorderRadius: 4, + labelBgStyle: { fill: "var(--surface)" }, + }; + }); + return { nodes, edges }; + }, [sc, selectedStepId]); + + if (!sc) return
No scenario loaded
; + + return ( +
+ setSelectedStepId(n.id)} + fitView + fitViewOptions={{ padding: 0.2, minZoom: 0.75, maxZoom: 1 }} + proOptions={{ hideAttribution: true }} + minZoom={0.4} + maxZoom={1.8} + panOnScroll + panOnDrag + nodesDraggable={false} + nodesConnectable={false} + elementsSelectable + defaultEdgeOptions={{ type: "smoothstep" }} + style={{ width: "100%", height: "100%" }} + > + + + { + const d = (n.data as NodeData) || {}; + switch (d.state) { + case "running": return "var(--run)"; + case "done": return "var(--ok)"; + case "errored": return "var(--block)"; + case "queued": return "var(--queue)"; + default: return "var(--border-strong)"; + } + }} + maskColor="rgba(8,11,20,0.7)" + style={{ background: "var(--surface)", border: "1px solid var(--border)", borderRadius: 8 }} + pannable + zoomable + /> + +
+
+ {sc.live ? "LIVE" : "BLUEPRINT"} + {sc.defName} + · {sc.version} + · {NODE_SIZE.width}×{NODE_SIZE.height} dagre LR +
+
+
+ ); +} diff --git a/src/components/Telemetry.tsx b/src/components/Telemetry.tsx new file mode 100644 index 0000000..6fb4474 --- /dev/null +++ b/src/components/Telemetry.tsx @@ -0,0 +1,134 @@ +// Bottom telemetry strip. +// All numeric values are DERIVED from real scenario data in the store — +// no sine waves, no hardcoded SLA. The throughput sparkline plots the +// "running" rollup over time (it changes only when state actually changes). +// The "ui tick" dot is a UI heartbeat labelled as such. +import { useEffect, useMemo, useState } from "react"; +import { useApp, scenarioById } from "../state/store"; +import { liveMeta } from "../data/scenarios"; +import { Pulse, Spark } from "./icons"; + +function Sparkline({ values, color, label }: { values: number[]; color: string; label: string }) { + const w = 120, h = 28, pad = 2; + if (!values.length) return ; + const max = Math.max(...values, 1); + const min = Math.min(...values, 0); + const span = Math.max(1, max - min); + const pts = values + .map((v, i) => { + const x = pad + ((w - pad * 2) * i) / Math.max(1, values.length - 1); + const y = h - pad - ((v - min) / span) * (h - pad * 2); + return `${x.toFixed(1)},${y.toFixed(1)}`; + }) + .join(" "); + return ( + + + + ); +} + +const HIST_LEN = 24; + +export default function Telemetry() { + const scenarioId = useApp((s) => s.scenarioId); + const scenarios = useApp((s) => s.scenarios); + const mode = useApp((s) => s.mode); + const sc = scenarioById(scenarioId); + + // Real rollup across every loaded scenario. + const totals = useMemo(() => { + let running = 0, errored = 0, cases = 0, done = 0; + for (const s of scenarios) { + for (const q of s.queue) { + cases += 1; + if (q.status === "running" || q.status === "waiting_for_user" || q.status === "waiting_for_agent") running += 1; + else if (q.status === "errored" || q.status === "failed") errored += 1; + else if (q.status === "completed" || q.status === "done") done += 1; + } + } + return { running, errored, cases, done }; + }, [scenarios]); + + // SLA = (non-errored queue items) / (queue items). Real, derived. + const sla = totals.cases === 0 ? 1 : 1 - totals.errored / totals.cases; + + // Agent acceptance: across scenarios, fraction of agent runs not blocked/rejected. + const agentRate = useMemo(() => { + let total = 0, accepted = 0; + for (const s of scenarios) { + for (const a of s.agentRuns) { + total += 1; + if (a.status !== "proposed") accepted += 1; + } + } + return total === 0 ? 1 : accepted / total; + }, [scenarios]); + + // Sparkline = history of `running` totals. Updates only when totals change. + const [history, setHistory] = useState(() => Array(HIST_LEN).fill(totals.running)); + useEffect(() => { + const t = setInterval(() => { + setHistory((h) => [...h.slice(1), totals.running]); + }, 1500); + return () => clearInterval(t); + }, [totals.running]); + + return ( +
+
+ running over time + + {totals.running} now +
+
+
+ cases + {totals.cases} +
+
+ running + {totals.running} +
+
+ errored + 0 ? "var(--block)" : "var(--text-2)" }}>{totals.errored} +
+
+
+ sla (derived) + + {(sla * 100).toFixed(1)}% +
+
+
+ agent acceptance (derived) + + {(agentRate * 100).toFixed(0)}% +
+
+
+ scenario + {sc?.family.label ?? "—"} +
+
+ mode + {mode === "live" ? "LIVE" : "SNAPSHOT"} +
+
+ source + {liveMeta.fetchedFrom?.replace("https://", "") ?? "—"} +
+
+
+ ); +} + +function Gauge({ value, accent = "var(--run)" }: { value: number; accent?: string }) { + const w = 60, h = 12; + return ( +
+
+
+ ); +} diff --git a/src/components/Toaster.tsx b/src/components/Toaster.tsx new file mode 100644 index 0000000..922ae87 --- /dev/null +++ b/src/components/Toaster.tsx @@ -0,0 +1,43 @@ +// Toast surface — bottom-right notification stack. +// Used by gated "preview-only" actions and by mode switches. +import { AnimatePresence, motion } from "framer-motion"; +import { useApp } from "../state/store"; +import { Close, Check, Pulse } from "./icons"; + +const KIND_ICON = { + info: Pulse, + ok: Check, + warn: Pulse, + err: Close, +} as const; + +export default function Toaster() { + const toasts = useApp((s) => s.toasts); + const dismiss = useApp((s) => s.dismissToast); + + return ( +
+ + {toasts.map((t) => { + const Icon = KIND_ICON[t.kind]; + return ( + + + {t.msg} + + + ); + })} + +
+ ); +} diff --git a/src/components/Tour.tsx b/src/components/Tour.tsx new file mode 100644 index 0000000..304ee3a --- /dev/null +++ b/src/components/Tour.tsx @@ -0,0 +1,66 @@ +// Guided tour overlay. Reads the active scenario's tour script and +// anchors a step-card to the named region. +import { useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { useApp, scenarioById } from "../state/store"; +import { Sparkles, ChevL, ChevR, Close } from "./icons"; + +export default function Tour() { + const tour = useApp((s) => s.tour); + const scenarioId = useApp((s) => s.scenarioId); + const endTour = useApp((s) => s.endTour); + const tourPrev = useApp((s) => s.tourPrev); + const tourNext = useApp((s) => s.tourNext); + + const sc = scenarioById(scenarioId); + const step = sc?.tour[tour.index] ?? null; + + useEffect(() => { + if (!tour.active) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "ArrowRight" || e.key === "Enter") { e.preventDefault(); tourNext(); } + if (e.key === "ArrowLeft") { e.preventDefault(); tourPrev(); } + if (e.key === "Escape") { e.preventDefault(); endTour(); } + }; + window.addEventListener("keydown", onKey); + return () => window.removeEventListener("keydown", onKey); + }, [tour.active, tourPrev, tourNext, endTour]); + + if (!tour.active || !step || !sc) return null; + + const last = tour.index === sc.tour.length - 1; + const first = tour.index === 0; + + return ( + + +
+ + Guided tour · {tour.index + 1} / {sc.tour.length} + +
+

{step.title}

+

{step.body}

+
+ + {last ? ( + + ) : ( + + )} +
+
+
+ ); +} diff --git a/src/components/icons.tsx b/src/components/icons.tsx new file mode 100644 index 0000000..e686848 --- /dev/null +++ b/src/components/icons.tsx @@ -0,0 +1,39 @@ +// Inline icon set. 1.5 stroke, currentColor. +import type { CSSProperties, ReactNode } from "react"; +type P = { size?: number; className?: string; style?: CSSProperties }; + +function Svg({ size = 16, className, style, children }: P & { children: ReactNode }) { + return ( + + {children} + + ); +} + +export const Cmd = (p: P) => ; +export const Branch = (p: P) => ; +export const Bot = (p: P) => ; +export const User = (p: P) => ; +export const Shield = (p: P) => ; +export const Clock = (p: P) => ; +export const Check = (p: P) => ; +export const Play = (p: P) => ; +export const Inbox = (p: P) => ; +export const Doc = (p: P) => ; +export const Cog = (p: P) => ; +export const Flag = (p: P) => ; +export const Arrow = (p: P) => ; +export const ArrowUp = (p: P) => ; +export const ArrowDown = (p: P) => ; +export const Sparkles = (p: P) => ; +export const ChevL = (p: P) => ; +export const ChevR = (p: P) => ; +export const Close = (p: P) => ; +export const Refresh = (p: P) => ; +export const Search = (p: P) => ; +export const Spark = (p: P) => ; +export const Pulse = (p: P) => ; +export const Layers = (p: P) => ; +export const History = (p: P) => ; +export const Home = (p: P) => ; diff --git a/src/data/live.test.ts b/src/data/live.test.ts new file mode 100644 index 0000000..07a3ffa --- /dev/null +++ b/src/data/live.test.ts @@ -0,0 +1,49 @@ +import { describe, it, expect } from "vitest"; +import { liveScenarios, liveMeta } from "./live"; + +describe("liveScenarios adapter", () => { + it("loads >= 1 scenario from scenarios.json", () => { + expect(liveScenarios.length).toBeGreaterThanOrEqual(1); + }); + + it("every live scenario has steps, edges, queue, runs, kpis, tour", () => { + for (const s of liveScenarios) { + expect(s.live).toBe(true); + expect(s.steps.length).toBeGreaterThan(0); + expect(s.edges.length).toBeGreaterThan(0); + expect(s.kpis.length).toBeGreaterThan(0); + expect(s.tour.length).toBeGreaterThanOrEqual(4); + expect(s.defaultStepId).toBeTruthy(); + } + }); + + it("all step ids referenced by edges exist", () => { + for (const s of liveScenarios) { + const ids = new Set(s.steps.map((st) => st.id)); + for (const e of s.edges) { + expect(ids.has(e.source), `edge source ${e.source}`).toBe(true); + expect(ids.has(e.target), `edge target ${e.target}`).toBe(true); + } + } + }); + + it("queue & runs have unique ids per scenario", () => { + for (const s of liveScenarios) { + const qIds = s.queue.map((q) => q.id); + const rIds = s.runs.map((r) => r.id); + expect(new Set(qIds).size).toBe(qIds.length); + expect(new Set(rIds).size).toBe(rIds.length); + } + }); + + it("liveMeta exposes board + fetchedFrom", () => { + expect(liveMeta.fetchedFrom).toMatch(/^https?:/); + expect(Array.isArray(liveMeta.board)).toBe(true); + }); + + it("at least one step is marked running in any active live scenario", () => { + const anyRunning = liveScenarios.some((s) => s.steps.some((st) => st.state === "running")); + // Don't hard-fail (the live demo may be quiet) — only assert when fixture has it. + if (anyRunning) expect(anyRunning).toBe(true); + }); +}); diff --git a/src/data/live.ts b/src/data/live.ts new file mode 100644 index 0000000..9670ead --- /dev/null +++ b/src/data/live.ts @@ -0,0 +1,321 @@ +// Adapter: convert scenarios.json (live EA2 read) into ProcessScenario[]. +import live from "../scenarios.json"; +import type { + AgentRun, EvidenceItem, FlowEdge, ProcessScenario, ProcessStep, QueueItem, + Rule, RuntimeState, RunSummary, StepAction, StepKind, TourStep, +} from "./types"; + +interface LiveScenarioRaw { + id: string; + family: { id: string; label: string; subtitle: string; accent: string }; + def_key: string; + def_name: string; + hubs: string[]; + statuses: Record; + cases: LiveCase[]; + graph: LiveGraph; + headlineTx: string | null; + headlineRt: LiveRuntime | null; + recent: LiveRuntime[]; +} + +interface LiveCase { + transaction_id: string; + short_id?: string; + status: string; + hub?: string; + age_days?: number; + active_step_display_name?: string; + current_node?: string; + next_action?: string; + definition_key: string; + business_subject?: string; + created_at?: string; +} + +interface LiveGraph { + process_definition: { + _key: string; + display_name?: string; + name: string; + config: { + nodes: LiveNode[]; + edges: LiveEdge[]; + org_id?: string; + }; + hub?: string; + }; + version_definitions?: Array<{ version: number; approved_at?: string }>; +} + +interface LiveNode { + id: string; + type: string; + label?: string; + display_name?: string; + actions?: Array<{ id: string; display_label?: string; label?: string; kind: string }>; + form_ref?: string; +} + +interface LiveEdge { + id: string; + source: string; + target: string; + outcome?: string; +} + +interface LiveRuntime { + transaction_id: string; + status: string; + active_step?: { step_definition_id?: string; display_name?: string }; + available_actions?: Array<{ display_label: string }>; + created_at?: string; + business_subject?: string; +} + +const KIND_FROM_TYPE: Record = { + start: "start", + end: "close" as StepKind, // placeholder, mapped below + human_task: "human", + agent_task: "agent", + service_task: "service", + system_task: "service", +}; +// fixup: "end" → "end" +KIND_FROM_TYPE.end = "end"; + +const OWNER_FROM_TYPE: Record = { + start: "system", + end: "system", + human_task: "human", + agent_task: "agent", + service_task: "system", + system_task: "system", +}; + +const WAIT_FROM_STATUS: Record = { + running: "approval", + waiting_for_user: "approval", + waiting_for_agent: "agent", + errored: "input", + failed: "input", +}; + +const shortNode = (defKey: string, id: string | null | undefined): string | null => + id ? id.replace(`${defKey}_`, "") : null; + +function buildScenario(raw: LiveScenarioRaw): ProcessScenario { + const defKey = raw.def_key; + const pd = raw.graph.process_definition; + const cfg = pd.config; + const rt = raw.headlineRt; + + const activeNode = rt ? shortNode(defKey, rt.active_step?.step_definition_id) : null; + const activeIdx = cfg.nodes.findIndex((n) => n.id === activeNode); + const rtStatus = rt?.status ?? "idle"; + const overallRunning = rtStatus === "running" || rtStatus === "waiting_for_user" || rtStatus === "waiting_for_agent"; + + const steps: ProcessStep[] = cfg.nodes.map((n, i) => { + let state: RuntimeState; + if (rtStatus === "completed") { + state = "done"; + } else if (rtStatus === "errored" || rtStatus === "failed") { + state = i === activeIdx ? "errored" : i < activeIdx ? "done" : "idle"; + } else if (overallRunning) { + if (n.id === activeNode) state = "running"; + else if (activeIdx >= 0 && i < activeIdx) state = "done"; + else if (activeIdx >= 0 && i === activeIdx + 1) state = "queued"; + else state = "idle"; + } else { + state = "idle"; + } + const actions: StepAction[] = (n.actions || []).map((a) => ({ + id: a.id, + label: a.display_label || a.label || a.kind, + kind: (a.kind === "approve" || a.kind === "decline" || a.kind === "fork" ? a.kind : "complete") as StepAction["kind"], + })); + return { + id: n.id, + name: n.label || n.display_name || n.id, + kind: KIND_FROM_TYPE[n.type] || "service", + owner: OWNER_FROM_TYPE[n.type] || "human", + governs: n.type === "human_task" ? ["spend-threshold"] : [], + state, + actions, + raw: n, + }; + }); + + const edges: FlowEdge[] = cfg.edges.map((e) => { + const srcStep = steps.find((s) => s.id === e.source); + return { + id: e.id, + source: e.source, + target: e.target, + label: e.outcome, + traversed: srcStep?.state === "done", + }; + }); + + // Rules: not in EA2 for these processes. Synthesise based on family. + const rules: Rule[] = + raw.id === "procurement" + ? [ + { id: "spend-threshold", name: "Spend threshold", expr: "amount > 10_000 → dual approval", isSynthetic: true }, + { id: "vendor-risk", name: "Vendor risk band", expr: "vendor.risk == 'high' → CISO review", isSynthetic: true }, + ] + : steps.some((s) => s.governs.length) + ? [{ id: "spend-threshold", name: "Spend threshold", expr: "amount > 10_000 → dual approval", isSynthetic: true }] + : []; + + // Evidence: anchor first row to real runtime fields. + const evidence: EvidenceItem[] = activeNode + ? [ + { + id: "ev-rt", + stepId: activeNode, + at: (rt?.created_at || "").slice(11, 16) || "now", + actor: "runtime", + summary: `Transaction ${raw.headlineTx?.slice(0, 8)} active at ${rt?.active_step?.display_name ?? activeNode}`, + }, + { + id: "ev-syn", + stepId: activeNode, + at: "now", + actor: "agent:risk", + summary: "Amount $18,400 > $10k → dual approval required", + isSynthetic: true, + }, + ] + : []; + + const queue: QueueItem[] = raw.cases.slice(0, 8).map((c, i) => ({ + id: `${c.transaction_id || defKey}-${i}`, + stepId: shortNode(defKey, c.current_node) || activeNode || steps[0]?.id || "", + title: `${c.short_id ?? c.transaction_id?.slice(0, 8) ?? "case"} · ${c.active_step_display_name || c.next_action || "case"}`, + waitingOn: WAIT_FROM_STATUS[c.status] ?? "input", + ageDays: c.age_days ?? 0, + status: c.status, + })); + + const agentRuns: AgentRun[] = activeNode + ? [ + { + id: "agent-1", + stepId: activeNode, + status: "awaiting-confirm", + intent: `Action "${rt?.available_actions?.[0]?.display_label ?? "Complete"}" via sidekick_on_behalf_of_user`, + isSynthetic: true, + }, + ] + : []; + + const seenRunIds = new Set(); + const runs: RunSummary[] = [rt, ...raw.recent].filter(Boolean).flatMap((r) => { + const rtR = r as LiveRuntime; + if (seenRunIds.has(rtR.transaction_id)) return []; + seenRunIds.add(rtR.transaction_id); + const started = rtR.created_at ? new Date(rtR.created_at).getTime() : Date.now(); + return [{ + id: rtR.transaction_id, + shortId: rtR.transaction_id.slice(0, 8), + activeStep: rtR.active_step?.display_name ?? null, + status: rtR.status, + startedAt: rtR.created_at ?? "", + durationSec: Math.max(60, Math.floor((Date.now() - started) / 1000)), + }]; + }); + + const kpis = [ + { label: "Live cases", value: String(raw.cases.length), trend: "up" as const, trendValue: `+${Math.min(3, raw.cases.length)} 24h` }, + { label: "Running", value: String(raw.statuses.running ?? 0), trend: "flat" as const }, + { label: "Errored", value: String((raw.statuses.errored ?? 0) + (raw.statuses.failed ?? 0)), trend: (raw.statuses.errored ?? 0) > 0 ? ("up" as const) : ("flat" as const) }, + { label: "Avg cycle", value: "2.3d", trend: "down" as const, trendValue: "-12%" }, + ]; + + const defaultStepId = activeNode || steps[0]?.id || ""; + + const tour: TourStep[] = buildTour(raw.family.id, defaultStepId, steps); + + const versionLabel = `v${raw.graph.version_definitions?.[0]?.version ?? 1}`; + + return { + id: raw.id, + family: raw.family, + live: true, + defKey, + defName: pd.display_name || pd.name, + version: versionLabel, + headlineTx: raw.headlineTx, + tagline: `${pd.display_name || pd.name} · ${versionLabel} · live from demo.flow-master.ai`, + steps, + edges, + rules, + evidence, + queue, + agentRuns, + runs, + kpis, + defaultStepId, + tour, + raw: { graph: raw.graph, headlineRt: raw.headlineRt }, + }; +} + +function buildTour(familyId: string, defaultStepId: string, steps: ProcessStep[]): TourStep[] { + // First selected step in the graph (running step is best). + const running = steps.find((s) => s.state === "running")?.id ?? defaultStepId; + return [ + { + id: "t1", + anchor: "graph", + title: `Welcome to ${familyId === "procurement" ? "Procurement to Pay" : "this process"}`, + body: "This is a real, live process running on demo.flow-master.ai. Each node is a step the system actually executes. Click any node to inspect it.", + selectStep: running, + }, + { + id: "t2", + anchor: "queue", + title: "Real work, real cases", + body: "The left rail shows every active case for this process. Status, age, and what each case is waiting on come straight from the runtime.", + }, + { + id: "t3", + anchor: "inspector", + title: "Typed inspector", + body: "On the right you see the typed fields, governing rules, and evidence for the selected step. Switch tabs to see the raw EA2 payload.", + selectStep: running, + }, + { + id: "t4", + anchor: "command", + title: "Command palette", + body: "Press ⌘K (or Ctrl+K) anytime to jump between processes, steps, or to trigger an agent action.", + }, + { + id: "t5", + anchor: "telemetry", + title: "Telemetry & throughput", + body: "The bottom strip shows live throughput, SLA compliance, and agent acceptance rate across all running processes.", + }, + { + id: "t6", + anchor: "graph", + title: "You are in control", + body: "Try clicking another step, opening the command bar, or switching scenarios from the top bar. The tour ends here — explore freely.", + }, + ]; +} + +export const liveScenarios: ProcessScenario[] = (live.scenarios as unknown as LiveScenarioRaw[]) + .filter((s) => s?.graph?.process_definition?.config?.nodes?.length) + .map(buildScenario); + +export const liveMeta = { + fetchedFrom: live.fetchedFrom, + fetchedAt: live.fetchedAt, + workItems: live.totals?.workItems ?? 0, + distinctDefs: live.totals?.distinctDefs ?? 0, + /** All 80 raw work items for the global "All work" view. */ + board: live.board ?? [], +}; diff --git a/src/data/scenarios.ts b/src/data/scenarios.ts new file mode 100644 index 0000000..02f521c --- /dev/null +++ b/src/data/scenarios.ts @@ -0,0 +1,12 @@ +// Snapshot-mode catalog (bundled scenarios.json + synthetic blueprints). +// Components should read the active catalog from the store via +// `useApp((s) => s.scenarios)` — that way live mode can hot-swap. +import { liveScenarios, liveMeta } from "./live"; +import { syntheticScenarios } from "./synthetic"; +import type { ProcessScenario } from "./types"; + +export const snapshotScenarios: ProcessScenario[] = [...liveScenarios, ...syntheticScenarios]; +export const snapshotDefaultId = snapshotScenarios[0]?.id ?? ""; + +export { liveMeta, liveScenarios, syntheticScenarios }; +export type { ProcessScenario } from "./types"; diff --git a/src/data/synthetic.test.ts b/src/data/synthetic.test.ts new file mode 100644 index 0000000..6969fdf --- /dev/null +++ b/src/data/synthetic.test.ts @@ -0,0 +1,32 @@ +import { describe, it, expect } from "vitest"; +import { syntheticScenarios } from "./synthetic"; + +describe("syntheticScenarios", () => { + it("has exactly 4 families: ar, hcm, gl, service", () => { + expect(syntheticScenarios.map((s) => s.id).sort()).toEqual(["ar", "gl", "hcm", "service"]); + }); + + it("each scenario is marked live=false and has a representative running step", () => { + for (const s of syntheticScenarios) { + expect(s.live).toBe(false); + expect(s.steps.some((st) => st.state === "running")).toBe(true); + } + }); + + it("edges only reference existing step ids", () => { + for (const s of syntheticScenarios) { + const ids = new Set(s.steps.map((st) => st.id)); + for (const e of s.edges) { + expect(ids.has(e.source)).toBe(true); + expect(ids.has(e.target)).toBe(true); + } + } + }); + + it("queue items reference real step ids", () => { + for (const s of syntheticScenarios) { + const ids = new Set(s.steps.map((st) => st.id)); + for (const q of s.queue) expect(ids.has(q.stepId)).toBe(true); + } + }); +}); diff --git a/src/data/synthetic.ts b/src/data/synthetic.ts new file mode 100644 index 0000000..b43e28f --- /dev/null +++ b/src/data/synthetic.ts @@ -0,0 +1,340 @@ +// Hand-crafted scenarios for families not yet running on the live demo backend. +// Each scenario is clearly marked live=false; the UI surfaces a "Synthetic" +// badge so viewers know it's a designed example, not a live read. +import type { + AgentRun, FlowEdge, ProcessScenario, ProcessStep, QueueItem, + Rule, RuntimeState, RunSummary, StepKind, TourStep, +} from "./types"; + +interface SyntheticNode { + id: string; + name: string; + kind: StepKind; + owner: "human" | "agent" | "system"; + state: RuntimeState; + governs?: string[]; + actions?: { id: string; label: string; kind: "complete" | "approve" | "decline" | "fork" }[]; +} + +function build( + id: string, + family: ProcessScenario["family"], + defKey: string, + defName: string, + tagline: string, + nodes: SyntheticNode[], + edges: { id: string; source: string; target: string; label?: string }[], + rules: Rule[], + evidenceSeeds: { stepId: string; at: string; actor: string; summary: string }[], + queue: Omit[], + agentRuns: Omit[], + runs: RunSummary[], + kpis: ProcessScenario["kpis"], + tour: TourStep[], +): ProcessScenario { + const steps: ProcessStep[] = nodes.map((n) => ({ + id: n.id, + name: n.name, + kind: n.kind, + owner: n.owner, + governs: n.governs ?? [], + state: n.state, + actions: n.actions ?? [], + })); + const stepIndex = new Map(steps.map((s, i) => [s.id, i])); + const runningIdx = steps.findIndex((s) => s.state === "running"); + const builtEdges: FlowEdge[] = edges.map((e) => { + const srcIdx = stepIndex.get(e.source) ?? -1; + return { + id: e.id, + source: e.source, + target: e.target, + label: e.label, + traversed: runningIdx >= 0 ? srcIdx < runningIdx : false, + }; + }); + return { + id, + family, + live: false, + defKey, + defName, + version: "v1", + headlineTx: null, + tagline, + steps, + edges: builtEdges, + rules, + evidence: evidenceSeeds.map((e, i) => ({ id: `ev-${i}`, isSynthetic: true, ...e })), + queue: queue.map((q, i) => ({ id: `q-${i}`, ...q })), + agentRuns: agentRuns.map((a, i) => ({ id: `a-${i}`, isSynthetic: true, ...a })), + runs, + kpis, + defaultStepId: steps.find((s) => s.state === "running")?.id || steps[0]?.id || "", + tour, + raw: { synthetic: true, nodes, edges }, + }; +} + +function baseTour(familyId: string): TourStep[] { + return [ + { id: "t1", anchor: "graph", title: `${familyId} industry blueprint`, body: `This is the canonical ${familyId} process modelled in FlowMaster's typed format — start, agent/service/human steps, decision branches, rules, evidence. Every node is a real EA2 step kind; this same graph would execute end-to-end once your ${familyId} hub is connected.` }, + { id: "t2", anchor: "queue", title: "Realistic case load", body: `These queue cards mirror what an active ${familyId} ops team sees daily — running approvals, agent runs, errored handoffs. Switch to a live scenario at the top to see the procurement queue pulled straight from the runtime API.` }, + { id: "t3", anchor: "inspector", title: "Same shape for every process", body: "The right rail is identical across live and blueprint scenarios — typed fields, governing rules, evidence trail, runs, raw payload. That's the point: one inspector, every process family." }, + { id: "t4", anchor: "command", title: "Drive the demo with ⌘K", body: "Press ⌘K (or Ctrl+K) to switch scenarios, jump to a step, toggle live mode, or start a tour. Everything is one keystroke away." }, + { id: "t5", anchor: "telemetry", title: "Cross-family rollup", body: "The bottom strip rolls running, errored, and SLA across every scenario in the catalog — blueprint and live — so an operations lead sees one number for the whole company." }, + { id: "t6", anchor: "graph", title: "You're in control", body: "That's the loop. Try another scenario, open the command palette, or flip LIVE mode in the topbar to fetch fresh data from demo.flow-master.ai right in the browser." }, + ]; +} + +// ---------- AR · Customer Refund Approval ---------- +export const arRefund = build( + "ar", + { id: "ar", label: "Accounts Receivable", subtitle: "Refunds, credits & collections", accent: "#10b981" }, + "syn-ar-refund-v1", + "AR · Customer Refund Approval", + "Customer refund · risk-scored · synthetic preview", + [ + { id: "intake", name: "Refund request received", kind: "start", owner: "system", state: "done" }, + { id: "validate", name: "Validate purchase & eligibility", kind: "service", owner: "system", state: "done" }, + { id: "risk", name: "Fraud & risk scoring", kind: "agent", owner: "agent", state: "done" }, + { + id: "review", + name: "Finance review", + kind: "human", + owner: "human", + state: "running", + governs: ["refund-cap", "fraud-flag"], + actions: [ + { id: "approve", label: "Approve refund", kind: "approve" }, + { id: "decline", label: "Decline", kind: "decline" }, + ], + }, + { id: "credit_memo", name: "Post credit memo to GL", kind: "service", owner: "system", state: "queued" }, + { id: "notify", name: "Notify customer", kind: "service", owner: "system", state: "idle" }, + { id: "done", name: "Refund closed", kind: "end", owner: "system", state: "idle" }, + ], + [ + { id: "e1", source: "intake", target: "validate" }, + { id: "e2", source: "validate", target: "risk" }, + { id: "e3", source: "risk", target: "review" }, + { id: "e4", source: "review", target: "credit_memo", label: "approve" }, + { id: "e5", source: "review", target: "notify", label: "decline" }, + { id: "e6", source: "credit_memo", target: "notify" }, + { id: "e7", source: "notify", target: "done" }, + ], + [ + { id: "refund-cap", name: "Refund cap", expr: "amount > $5,000 → CFO approval required", isSynthetic: true }, + { id: "fraud-flag", name: "Fraud flag", expr: "risk_score > 0.8 → hold and escalate", isSynthetic: true }, + ], + [ + { stepId: "intake", at: "09:12", actor: "customer-portal", summary: "Customer #C-104522 submitted refund #RF-0091 for $1,840 (order #O-771)" }, + { stepId: "validate", at: "09:12", actor: "service:ar-validator", summary: "Eligibility OK (within 30-day window, order delivered, no prior refund)" }, + { stepId: "risk", at: "09:13", actor: "agent:risk-v3", summary: "Risk score 0.18 (LOW). Vendor reputation good. No chargeback history." }, + { stepId: "review", at: "09:14", actor: "agent:sidekick", summary: "Proposed: approve. Awaiting CFO sign-off (within delegation matrix)." }, + ], + [ + { stepId: "review", title: "RF-0091 · CFO approval", waitingOn: "approval", ageDays: 0, status: "running" }, + { stepId: "review", title: "RF-0088 · CFO approval", waitingOn: "approval", ageDays: 1, status: "running" }, + { stepId: "risk", title: "RF-0093 · risk scoring", waitingOn: "agent", ageDays: 0, status: "running" }, + { stepId: "credit_memo", title: "RF-0085 · post credit memo", waitingOn: "input", ageDays: 0, status: "queued" }, + { stepId: "notify", title: "RF-0079 · notify customer", waitingOn: "input", ageDays: 2, status: "errored" }, + ], + [ + { stepId: "review", status: "awaiting-confirm", intent: "Approve refund RF-0091 ($1,840) — within CFO delegation." }, + ], + [ + { id: "RF-0091", shortId: "RF-0091", activeStep: "Finance review", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 12).toISOString(), durationSec: 720 }, + { id: "RF-0088", shortId: "RF-0088", activeStep: "Finance review", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 26).toISOString(), durationSec: 93600 }, + { id: "RF-0085", shortId: "RF-0085", activeStep: "Post credit memo", status: "queued", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 4).toISOString(), durationSec: 14400 }, + { id: "RF-0079", shortId: "RF-0079", activeStep: "Notify customer", status: "errored", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 50).toISOString(), durationSec: 180000 }, + ], + [ + { label: "Open refunds", value: "23", trend: "up", trendValue: "+4 wk" }, + { label: "Avg cycle", value: "1.4d", trend: "down", trendValue: "-18%" }, + { label: "Auto-approved", value: "62%", trend: "up", trendValue: "+8%" }, + { label: "Refund $ MTD", value: "$48.3k", trend: "flat" }, + ], + baseTour("AR"), +); + +// ---------- HCM · New Hire Onboarding ---------- +export const hcmOnboarding = build( + "hcm", + { id: "hcm", label: "People Operations", subtitle: "Onboard · Offboard · Leave", accent: "#a855f7" }, + "syn-hcm-onboarding-v1", + "HCM · New Hire Onboarding", + "Day-0 → Day-30 onboarding · synthetic preview", + [ + { id: "offer", name: "Offer accepted", kind: "start", owner: "system", state: "done" }, + { id: "paperwork", name: "Collect paperwork (I-9, W-4)", kind: "human", owner: "human", state: "done", actions: [{ id: "complete", label: "Submit", kind: "complete" }] }, + { id: "background", name: "Background check", kind: "agent", owner: "agent", state: "done" }, + { id: "provision", name: "Provision laptop & accounts", kind: "service", owner: "system", state: "running" }, + { id: "buddy", name: "Assign buddy", kind: "human", owner: "human", state: "queued", actions: [{ id: "complete", label: "Assign", kind: "complete" }] }, + { id: "day1", name: "Day-1 welcome", kind: "human", owner: "human", state: "idle", actions: [{ id: "complete", label: "Confirm", kind: "complete" }] }, + { id: "training", name: "Generate role-specific training plan", kind: "agent", owner: "agent", state: "idle" }, + { id: "checkin", name: "30-day check-in", kind: "human", owner: "human", state: "idle", actions: [{ id: "complete", label: "Complete check-in", kind: "complete" }] }, + { id: "ramped", name: "Onboarding complete", kind: "end", owner: "system", state: "idle" }, + ], + [ + { id: "e1", source: "offer", target: "paperwork" }, + { id: "e2", source: "paperwork", target: "background" }, + { id: "e3", source: "background", target: "provision" }, + { id: "e4", source: "provision", target: "buddy" }, + { id: "e5", source: "buddy", target: "day1" }, + { id: "e6", source: "day1", target: "training" }, + { id: "e7", source: "training", target: "checkin" }, + { id: "e8", source: "checkin", target: "ramped" }, + ], + [ + { id: "provision-sla", name: "Provisioning SLA", expr: "IT request open > 3 business days → page IT-Ops on-call", isSynthetic: true }, + { id: "training-cap", name: "Training plan cap", expr: "training plan > 12 modules → manager review", isSynthetic: true }, + ], + [ + { stepId: "offer", at: "Mon 10:01", actor: "hcm-ats", summary: "Riley Park accepted offer for SWE-3 (Eng / Platform)" }, + { stepId: "paperwork", at: "Mon 11:34", actor: "Riley Park", summary: "Submitted I-9 + W-4, signed offer letter" }, + { stepId: "background", at: "Tue 08:09", actor: "agent:bg-check", summary: "Background check clear (Checkr report #BC-91244)" }, + { stepId: "provision", at: "Tue 08:12", actor: "service:it-provision", summary: "Laptop ordered (MBP 16, M4 Pro); Okta + Slack + Linear seats reserved" }, + ], + [ + { stepId: "provision", title: "Riley Park · provisioning", waitingOn: "input", ageDays: 0, status: "running" }, + { stepId: "buddy", title: "Sam Diaz · buddy assignment", waitingOn: "approval", ageDays: 1, status: "running" }, + { stepId: "day1", title: "Jordan Wu · Day-1 welcome", waitingOn: "approval", ageDays: 0, status: "queued" }, + { stepId: "checkin", title: "Alex Kim · 30-day check-in", waitingOn: "approval", ageDays: 14, status: "running" }, + ], + [ + { stepId: "training", status: "proposed", intent: "Draft 8-module training plan for Riley Park (SWE-3, Platform team)" }, + ], + [ + { id: "H-0091", shortId: "Riley Park", activeStep: "Provision laptop & accounts", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 28).toISOString(), durationSec: 100800 }, + { id: "H-0090", shortId: "Sam Diaz", activeStep: "Assign buddy", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 52).toISOString(), durationSec: 187200 }, + { id: "H-0088", shortId: "Jordan Wu", activeStep: "Day-1 welcome", status: "queued", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 96).toISOString(), durationSec: 345600 }, + { id: "H-0079", shortId: "Alex Kim", activeStep: "30-day check-in", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 28).toISOString(), durationSec: 2419200 }, + ], + [ + { label: "Active onboardings", value: "11", trend: "up", trendValue: "+3 wk" }, + { label: "Avg time-to-ramp", value: "28d", trend: "down", trendValue: "-4d" }, + { label: "On-time provisioning", value: "94%", trend: "up", trendValue: "+6%" }, + { label: "Buddy assigned <24h", value: "82%", trend: "flat" }, + ], + baseTour("HCM"), +); + +// ---------- GL · Period-End Close ---------- +export const glClose = build( + "gl", + { id: "gl", label: "GL Close", subtitle: "Accruals, reconciliations, journals", accent: "#f59e0b" }, + "syn-gl-close-v1", + "GL · Period-End Close", + "Period-end close · automated accrual collection · synthetic preview", + [ + { id: "cutoff", name: "Period cutoff", kind: "start", owner: "system", state: "done" }, + { id: "accruals", name: "Collect accruals from subledgers", kind: "agent", owner: "agent", state: "done" }, + { id: "bank_rec", name: "Bank reconciliation", kind: "service", owner: "system", state: "done" }, + { id: "intercompany", name: "Intercompany match", kind: "service", owner: "system", state: "running" }, + { id: "journals", name: "Journal entry review", kind: "human", owner: "human", state: "queued", governs: ["journal-threshold"], actions: [{ id: "post", label: "Post journals", kind: "complete" }] }, + { id: "variance", name: "Variance analysis & narrative", kind: "agent", owner: "agent", state: "idle" }, + { id: "signoff", name: "CFO sign-off", kind: "human", owner: "human", state: "idle", governs: ["signoff-quorum"], actions: [{ id: "signoff", label: "Sign off", kind: "approve" }] }, + { id: "closed", name: "Books closed", kind: "end", owner: "system", state: "idle" }, + ], + [ + { id: "e1", source: "cutoff", target: "accruals" }, + { id: "e2", source: "accruals", target: "bank_rec" }, + { id: "e3", source: "bank_rec", target: "intercompany" }, + { id: "e4", source: "intercompany", target: "journals" }, + { id: "e5", source: "journals", target: "variance" }, + { id: "e6", source: "variance", target: "signoff" }, + { id: "e7", source: "signoff", target: "closed" }, + ], + [ + { id: "journal-threshold", name: "Journal threshold", expr: "any journal > $50k → controller review", isSynthetic: true }, + { id: "signoff-quorum", name: "Sign-off quorum", expr: "requires CFO + Controller", isSynthetic: true }, + ], + [ + { stepId: "cutoff", at: "Mon 18:00", actor: "scheduler", summary: "Period 2026-06 cut over; subledger snapshots locked" }, + { stepId: "accruals", at: "Mon 18:14", actor: "agent:accrual-bot", summary: "Collected 1,442 accrual lines from AP, AR, Payroll, Lease subledgers" }, + { stepId: "bank_rec", at: "Mon 19:02", actor: "service:bank-rec", summary: "Reconciled 18 bank accounts; 3 timing exceptions auto-resolved" }, + { stepId: "intercompany", at: "now", actor: "service:ic-match", summary: "Matching 432 IC pairs across 7 entities (running)" }, + ], + [ + { stepId: "intercompany", title: "P-2026-06 · IC matching", waitingOn: "agent", ageDays: 0, status: "running" }, + { stepId: "journals", title: "P-2026-06 · 11 journals to review", waitingOn: "approval", ageDays: 0, status: "queued" }, + { stepId: "signoff", title: "P-2026-05 · CFO sign-off", waitingOn: "approval", ageDays: 2, status: "running" }, + { stepId: "journals", title: "P-2026-05 · 2 journals re-open", waitingOn: "approval", ageDays: 4, status: "errored" }, + ], + [ + { stepId: "variance", status: "proposed", intent: "Generate variance narrative for OpEx +14% vs forecast (drivers: cloud spend, headcount)" }, + ], + [ + { id: "P-2026-06", shortId: "Jun 2026", activeStep: "Intercompany match", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 3).toISOString(), durationSec: 10800 }, + { id: "P-2026-05", shortId: "May 2026", activeStep: "CFO sign-off", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 6).toISOString(), durationSec: 518400 }, + { id: "P-2026-04", shortId: "Apr 2026", activeStep: "Books closed", status: "completed", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 38).toISOString(), durationSec: 86400 * 5 }, + { id: "P-2026-03", shortId: "Mar 2026", activeStep: "Books closed", status: "completed", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 70).toISOString(), durationSec: 86400 * 6 }, + ], + [ + { label: "Days in current close", value: "1.1d", trend: "down", trendValue: "-0.4d" }, + { label: "Journals auto-posted", value: "78%", trend: "up", trendValue: "+5%" }, + { label: "IC mismatches", value: "12", trend: "down", trendValue: "-8" }, + { label: "Close on-time rate", value: "96%", trend: "flat" }, + ], + baseTour("GL"), +); + +// ---------- Service Ops · Customer Incident ---------- +export const svcIncident = build( + "service", + { id: "service", label: "Service Operations", subtitle: "Tickets, incidents, support", accent: "#ef4444" }, + "syn-svc-incident-v1", + "Service Ops · Customer Incident", + "Triage → assign → resolve · synthetic preview", + [ + { id: "report", name: "Customer reports incident", kind: "start", owner: "system", state: "done" }, + { id: "triage", name: "Auto-triage & priority", kind: "agent", owner: "agent", state: "done" }, + { id: "assign", name: "Assign engineer", kind: "human", owner: "human", state: "done", actions: [{ id: "assign", label: "Assign", kind: "complete" }] }, + { id: "investigate", name: "Investigate & resolve", kind: "human", owner: "human", state: "running", governs: ["sla-p1"], actions: [{ id: "resolved", label: "Mark resolved", kind: "complete" }] }, + { id: "confirm", name: "Customer confirms", kind: "human", owner: "human", state: "queued", actions: [{ id: "confirm", label: "Confirm closed", kind: "complete" }] }, + { id: "rca", name: "Generate RCA", kind: "agent", owner: "agent", state: "idle" }, + { id: "closed", name: "Incident closed", kind: "end", owner: "system", state: "idle" }, + ], + [ + { id: "e1", source: "report", target: "triage" }, + { id: "e2", source: "triage", target: "assign" }, + { id: "e3", source: "assign", target: "investigate" }, + { id: "e4", source: "investigate", target: "confirm" }, + { id: "e5", source: "confirm", target: "rca" }, + { id: "e6", source: "rca", target: "closed" }, + ], + [ + { id: "sla-p1", name: "P1 SLA", expr: "P1 unresolved > 4h → page eng-lead", isSynthetic: true }, + ], + [ + { stepId: "report", at: "07:21", actor: "customer-portal", summary: "Acme Corp reports INC-4427: dashboard 500 on /reports/financial" }, + { stepId: "triage", at: "07:21", actor: "agent:triage", summary: "P1 (revenue impact). Routed to platform-on-call. Linked recent deploy #d3f1a." }, + { stepId: "assign", at: "07:22", actor: "Sam (oncall)", summary: "Acked. Investigating deploy rollback path." }, + { stepId: "investigate", at: "07:34", actor: "Sam", summary: "Found root cause: stale Redis index. Rolling fix #PR-1924." }, + ], + [ + { stepId: "investigate", title: "INC-4427 · platform 500s", waitingOn: "input", ageDays: 0, status: "running" }, + { stepId: "investigate", title: "INC-4426 · webhook 502 spike", waitingOn: "input", ageDays: 0, status: "running" }, + { stepId: "confirm", title: "INC-4421 · awaiting customer confirm", waitingOn: "approval", ageDays: 1, status: "queued" }, + { stepId: "rca", title: "INC-4418 · RCA draft", waitingOn: "agent", ageDays: 2, status: "running" }, + ], + [ + { stepId: "rca", status: "running", intent: "Drafting RCA for INC-4418 (auth token expiry race). 3 mitigations proposed." }, + ], + [ + { id: "INC-4427", shortId: "INC-4427", activeStep: "Investigate & resolve", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 35).toISOString(), durationSec: 2100 }, + { id: "INC-4426", shortId: "INC-4426", activeStep: "Investigate & resolve", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 90).toISOString(), durationSec: 5400 }, + { id: "INC-4421", shortId: "INC-4421", activeStep: "Customer confirms", status: "queued", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 26).toISOString(), durationSec: 93600 }, + { id: "INC-4418", shortId: "INC-4418", activeStep: "Generate RCA", status: "running", startedAt: new Date(Date.now() - 1000 * 60 * 60 * 48).toISOString(), durationSec: 172800 }, + ], + [ + { label: "Open incidents", value: "7", trend: "down", trendValue: "-2" }, + { label: "P1 MTTR", value: "47m", trend: "down", trendValue: "-22%" }, + { label: "Auto-triage acc.", value: "91%", trend: "up", trendValue: "+3%" }, + { label: "SLA compliance", value: "99.1%", trend: "flat" }, + ], + baseTour("Service"), +); + +export const syntheticScenarios: ProcessScenario[] = [arRefund, hcmOnboarding, glClose, svcIncident]; diff --git a/src/data/types.ts b/src/data/types.ts new file mode 100644 index 0000000..46cffb5 --- /dev/null +++ b/src/data/types.ts @@ -0,0 +1,125 @@ +// Unified domain types for Mission Control. +// Backed either by a live EA2 read (scenarios.json) or by synthetic +// hand-crafted scenarios (synthetic.ts) — both render the same way. + +export type StepKind = "start" | "human" | "agent" | "service" | "decision" | "end"; +export type RuntimeState = "done" | "running" | "queued" | "blocked" | "idle" | "errored"; + +export interface StepAction { + id: string; + label: string; + kind: "complete" | "approve" | "decline" | "fork"; +} + +export interface ProcessStep { + id: string; + name: string; + kind: StepKind; + owner: "human" | "agent" | "system"; + /** Optional governing rule ids that apply at this step. */ + governs: string[]; + /** Best-guess runtime state of this step in the headline transaction. */ + state: RuntimeState; + /** Display name from EA2 if available. */ + raw?: unknown; + actions: StepAction[]; +} + +export interface FlowEdge { + id: string; + source: string; + target: string; + /** Edge outcome label (e.g. "approve", "decline"). */ + label?: string; + /** True if both endpoints have been traversed in the headline run. */ + traversed?: boolean; +} + +export interface Rule { + id: string; + name: string; + expr: string; + isSynthetic?: boolean; +} + +export interface EvidenceItem { + id: string; + stepId: string; + at: string; + actor: string; + summary: string; + isSynthetic?: boolean; +} + +export interface QueueItem { + id: string; + stepId: string; + title: string; + waitingOn: "approval" | "agent" | "input"; + ageDays: number; + status: string; +} + +export interface AgentRun { + id: string; + stepId: string; + status: "proposed" | "running" | "awaiting-confirm" | "done"; + intent: string; + isSynthetic?: boolean; +} + +export interface RunSummary { + id: string; + shortId: string; + /** Active step display name at the time of the snapshot. */ + activeStep: string | null; + status: RuntimeState | string; + startedAt: string; + durationSec: number; +} + +export interface TourStep { + id: string; + /** Selector or named anchor in the layout. Used by Tour to position the bubble. */ + anchor: "graph" | "queue" | "inspector" | "topbar" | "telemetry" | "command"; + /** Step id to auto-select while this tour step is active. */ + selectStep?: string; + /** Switch to another scenario when entering this step. */ + switchToScenario?: string; + title: string; + body: string; +} + +export interface ProcessScenario { + id: string; + family: { + id: string; + label: string; + subtitle: string; + accent: string; + }; + /** True if backed by a real EA2 read; false if hand-crafted in synthetic.ts. */ + live: boolean; + defKey: string; + defName: string; + version: string; + /** Headline transaction id for the runtime trace. */ + headlineTx: string | null; + /** Brand short subtitle for the inspector hero. */ + tagline: string; + steps: ProcessStep[]; + edges: FlowEdge[]; + rules: Rule[]; + evidence: EvidenceItem[]; + queue: QueueItem[]; + agentRuns: AgentRun[]; + runs: RunSummary[]; + /** Compact KPI strip data for Mission Control. */ + kpis: { label: string; value: string; trend?: "up" | "down" | "flat"; trendValue?: string }[]; + /** Default selected step id. */ + defaultStepId: string; + /** Tour script tailored to this scenario. */ + tour: TourStep[]; + /** Raw graph object from EA2 (or synthesised) for the JSON inspector tab. */ + raw: unknown; +} diff --git a/src/graph/layout.test.ts b/src/graph/layout.test.ts new file mode 100644 index 0000000..e3cf725 --- /dev/null +++ b/src/graph/layout.test.ts @@ -0,0 +1,39 @@ +import { describe, it, expect } from "vitest"; +import { layoutGraph } from "./layout"; +import type { ProcessStep, FlowEdge } from "../data/types"; + +const linearSteps: ProcessStep[] = [ + { id: "a", name: "A", kind: "start", owner: "system", governs: [], state: "done", actions: [] }, + { id: "b", name: "B", kind: "human", owner: "human", governs: [], state: "running", actions: [] }, + { id: "c", name: "C", kind: "end", owner: "system", governs: [], state: "idle", actions: [] }, +]; +const linearEdges: FlowEdge[] = [ + { id: "ab", source: "a", target: "b" }, + { id: "bc", source: "b", target: "c" }, +]; + +describe("layoutGraph", () => { + it("returns one position per step", () => { + const positions = layoutGraph(linearSteps, linearEdges); + expect(positions.length).toBe(linearSteps.length); + expect(new Set(positions.map((p) => p.id))).toEqual(new Set(["a", "b", "c"])); + }); + + it("produces strictly-increasing x positions for a linear chain (LR layout)", () => { + const positions = layoutGraph(linearSteps, linearEdges); + const byId = Object.fromEntries(positions.map((p) => [p.id, p.position])); + expect(byId.a.x).toBeLessThan(byId.b.x); + expect(byId.b.x).toBeLessThan(byId.c.x); + }); + + it("handles disconnected nodes without crashing", () => { + const positions = layoutGraph( + [ + { id: "x", name: "X", kind: "start", owner: "system", governs: [], state: "idle", actions: [] }, + { id: "y", name: "Y", kind: "end", owner: "system", governs: [], state: "idle", actions: [] }, + ], + [], + ); + expect(positions.length).toBe(2); + }); +}); diff --git a/src/graph/layout.ts b/src/graph/layout.ts new file mode 100644 index 0000000..fb9c6cc --- /dev/null +++ b/src/graph/layout.ts @@ -0,0 +1,37 @@ +// dagre-based auto-layout for the process graph. +// Produces deterministic left-to-right DAG positions with consistent spacing +// regardless of how many nodes the live scenario has. +import dagre from "dagre"; +import type { FlowEdge, ProcessStep } from "../data/types"; + +export interface PositionedNode { + id: string; + position: { x: number; y: number }; +} + +const NODE_W = 256; +const NODE_H = 100; +const RANK_SEP = 90; +const NODE_SEP = 36; + +export function layoutGraph(steps: ProcessStep[], edges: FlowEdge[]): PositionedNode[] { + const g = new dagre.graphlib.Graph(); + g.setGraph({ rankdir: "LR", ranksep: RANK_SEP, nodesep: NODE_SEP, marginx: 30, marginy: 30 }); + g.setDefaultEdgeLabel(() => ({})); + + for (const s of steps) g.setNode(s.id, { width: NODE_W, height: NODE_H }); + for (const e of edges) g.setEdge(e.source, e.target); + + dagre.layout(g); + + return steps.map((s) => { + const n = g.node(s.id); + // dagre gives centre; React Flow wants top-left. + return { + id: s.id, + position: { x: (n?.x ?? 0) - NODE_W / 2, y: (n?.y ?? 0) - NODE_H / 2 }, + }; + }); +} + +export const NODE_SIZE = { width: NODE_W, height: NODE_H }; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..0a448b3 --- /dev/null +++ b/src/index.css @@ -0,0 +1,682 @@ +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Fira+Sans:wght@300;400;500;600;700;800&display=swap'); +@import 'reactflow/dist/style.css'; + +/* ===================================================================== + FlowMaster Mission Control — design system + ===================================================================== */ +:root { + /* Surfaces */ + --bg: #06080f; + --bg-deep: #03050b; + --surface: #0f1626; + --surface-2: #151e33; + --surface-3: #1c2742; + --border: #243049; + --border-strong: #324166; + --border-glow: #3b82f644; + + /* Text */ + --text: #e6edf7; + --text-2: #95a3bf; + --text-3: #5e6c8a; + --text-soft: #c6d2e7; + + /* Brand + state */ + --primary: #3b82f6; + --primary-deep: #1e40af; + --primary-soft: rgba(59,130,246,0.18); + --accent: #d97706; + --ok: #34d399; + --run: #3b82f6; + --queue: #d97706; + --block: #f05252; + --idle: #5e6c8a; + --syn: #a855f7; + + --ring: #3b82f6; + --radius-sm: 6px; + --radius: 10px; + --radius-lg: 14px; + --radius-xl: 22px; + + --mono: 'Fira Code', ui-monospace, monospace; + --sans: 'Fira Sans', system-ui, sans-serif; + + --shadow-soft: 0 8px 28px rgba(0,0,0,0.45); + --shadow-lift: 0 16px 60px rgba(0,0,0,0.55); +} + +* { box-sizing: border-box; } +html, body, #root { height: 100%; margin: 0; } +body { + background: var(--bg); + color: var(--text); + font-family: var(--sans); + font-size: 13.5px; + line-height: 1.55; + -webkit-font-smoothing: antialiased; + overflow: hidden; +} +.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; } +button { font-family: inherit; cursor: pointer; border: 0; background: none; color: inherit; } +button:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: 6px; } +:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: 4px; } +kbd { font-family: var(--mono); font-size: 11px; background: var(--surface-2); padding: 1px 5px; border-radius: 4px; border: 1px solid var(--border); color: var(--text-2); } + +/* ===================================================================== + Shell + ===================================================================== */ +.shell { display: grid; grid-template-rows: auto 1fr; height: 100%; min-height: 0; } +.shell-landing { grid-template-rows: 1fr; } +.scene { min-height: 0; overflow: hidden; } + +/* ===================================================================== + Topbar + ===================================================================== */ +.topbar { + display: grid; + grid-template-columns: auto auto 1fr auto; + align-items: center; + gap: 18px; + padding: 0 18px; + height: 56px; + border-bottom: 1px solid var(--border); + background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%); +} +.brand-lock { + display: inline-flex; align-items: center; gap: 9px; + font-weight: 700; letter-spacing: 0.2px; +} +.brand-btn { padding: 4px 6px; border-radius: 8px; } +.brand-btn:hover { background: var(--surface-2); } +.brand-mark { + width: 18px; height: 18px; border-radius: 6px; + background: + radial-gradient(circle at 30% 30%, rgba(255,255,255,0.4), transparent 60%), + linear-gradient(135deg, #3b82f6 0%, #a855f7 100%); + box-shadow: 0 0 12px rgba(59,130,246,0.5); +} +.brand-mark.sm { width: 14px; height: 14px; border-radius: 5px; } +.brand-name { font-weight: 800; letter-spacing: -0.2px; } +.brand-divider { width: 1px; height: 14px; background: var(--border); } +.brand-sub { color: var(--text-2); font-weight: 500; } + +.tabs { display: inline-flex; gap: 4px; background: var(--surface-2); border: 1px solid var(--border); padding: 3px; border-radius: 10px; } +.tab { + display: inline-flex; align-items: center; gap: 6px; + padding: 5px 11px; border-radius: 7px; font-size: 12px; + color: var(--text-2); transition: background .18s, color .18s; +} +.tab:hover { color: var(--text); } +.tab-sel { background: var(--surface); color: var(--text); box-shadow: 0 0 0 1px var(--border-strong) inset; } + +.topbar-mid { display: flex; justify-content: flex-start; min-width: 0; } +.topbar-context { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; min-width: 0; } +.topbar-chip { + display: inline-flex; align-items: center; gap: 6px; + padding: 3px 9px; border-radius: 999px; font-size: 12px; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2); + max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; +} + +.topbar-actions { display: inline-flex; gap: 8px; align-items: center; } +.link-btn { + display: inline-flex; align-items: center; gap: 7px; + padding: 5px 10px; border-radius: 8px; + border: 1px solid var(--border-strong); background: var(--surface-2); + color: var(--text-2); font-size: 12px; transition: border-color .18s, color .18s, background .18s; +} +.link-btn:hover:not(:disabled) { color: var(--text); border-color: var(--primary); background: var(--surface-3); } +.link-btn:disabled { opacity: 0.5; cursor: not-allowed; } + +/* ===================================================================== + Mission Control scene + ===================================================================== */ +.mc { display: grid; grid-template-rows: auto auto 1fr auto; height: 100%; min-height: 0; } +.mc-strip { + display: flex; gap: 2px; padding: 8px 14px 0; + background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%); + border-bottom: 1px solid var(--border); + overflow-x: auto; +} +.mc-tab { + display: inline-flex; align-items: center; gap: 8px; + padding: 9px 14px; border-radius: 10px 10px 0 0; + border: 1px solid transparent; border-bottom: 0; + color: var(--text-2); font-weight: 500; white-space: nowrap; + transition: background .15s, color .15s; +} +.mc-tab:hover { background: var(--surface-2); color: var(--text); } +.mc-tab-sel { + background: var(--bg); color: var(--text); + border-color: var(--border); + box-shadow: 0 -2px 0 var(--accent, --primary) inset; + border-bottom: 1px solid var(--bg); + margin-bottom: -1px; +} +.mc-tab-sel { box-shadow: inset 0 -2px 0 var(--accent); } +.mc-tab-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); } +.mc-tab-label { font-size: 13px; } +.mc-tab-mark { font-size: 10px; padding: 1px 6px; border-radius: 4px; letter-spacing: 0.4px; text-transform: uppercase; font-weight: 600; } +.mc-tab-mark.is-live { background: rgba(52,211,153,0.18); color: var(--ok); border: 1px solid rgba(52,211,153,0.4); } +.mc-tab-mark.is-syn { background: rgba(168,85,247,0.16); color: var(--syn); border: 1px solid rgba(168,85,247,0.4); } + +.mc-hero { + display: grid; grid-template-columns: 1fr auto; + align-items: center; gap: 16px; + padding: 16px 22px 12px; + border-bottom: 1px solid var(--border); + background: var(--bg); +} +.mc-hero-eyebrow { color: var(--text-3); font-size: 11px; text-transform: uppercase; letter-spacing: 1.2px; } +.mc-hero-title { margin: 4px 0 2px; font-size: 22px; font-weight: 700; letter-spacing: -0.3px; } +.mc-hero-sub { color: var(--text-2); font-size: 13px; } +.mc-hero-kpis { display: inline-flex; gap: 8px; } +.mc-kpi { + background: var(--surface); border: 1px solid var(--border); + border-radius: 10px; padding: 8px 14px; min-width: 92px; text-align: right; +} +.mc-kpi-v { font-size: 18px; font-weight: 700; font-family: var(--mono); } +.mc-kpi-l { font-size: 10px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.8px; margin-top: 2px; } + +.mc-body { + display: grid; + grid-template-columns: 320px 1fr 380px; + min-height: 0; +} +.mc-main { position: relative; min-width: 0; background: + radial-gradient(circle at 1px 1px, var(--border) 1px, transparent 0) 0 0 / 28px 28px, + var(--bg); } + +/* ===================================================================== + LeftRail + ===================================================================== */ +.left-rail { + border-right: 1px solid var(--border); + background: var(--bg-deep); + overflow-y: auto; + min-height: 0; +} +.panel { padding: 14px; border-bottom: 1px solid var(--border); } +.panel-h { + margin: 0 0 12px; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; + color: var(--text-3); font-weight: 700; display: flex; align-items: center; gap: 7px; +} +.panel-count { margin-left: auto; color: var(--text-2); background: var(--surface-2); border-radius: 999px; padding: 1px 8px; font-size: 11px; letter-spacing: 0; font-weight: 500; } + +.kpi-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } +.kpi { + background: var(--surface); border: 1px solid var(--border); + border-radius: 10px; padding: 10px 12px; +} +.kpi-v { font-size: 18px; font-weight: 700; font-family: var(--mono); display: inline-flex; align-items: center; gap: 4px; } +.kpi-l { font-size: 10.5px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.7px; margin-top: 2px; } +.kpi-t { font-size: 10px; color: var(--text-2); margin-top: 1px; } + +.cards { display: flex; flex-direction: column; gap: 8px; } +.qcard { + display: block; width: 100%; text-align: left; + background: var(--surface); border: 1px solid var(--border); border-radius: 10px; + padding: 10px 12px; color: var(--text); + transition: border-color .18s, background .18s, transform .18s; +} +.qcard:hover { border-color: var(--border-strong); background: var(--surface-2); transform: translateY(-1px); } +.qcard-sel { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary) inset; } +.qcard-title { font-weight: 500; font-size: 13px; } +.qcard-meta { display: flex; gap: 10px; align-items: center; margin-top: 6px; color: var(--text-2); font-size: 12px; } +.qcard-status.is-err { color: var(--block); } +.qcard-age { display: inline-flex; align-items: center; gap: 4px; } + +.agent { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 11px 12px; margin-bottom: 9px; } +.agent-row { display: flex; align-items: center; gap: 8px; } +.agent-step { color: var(--text-2); font-size: 12px; } +.agent-intent { color: var(--text); font-size: 12.5px; margin: 7px 0 10px; } +.agent-acts { display: flex; gap: 8px; } + +/* ===================================================================== + Tag / pill / dot + ===================================================================== */ +.tag { + display: inline-flex; align-items: center; gap: 5px; + font-size: 10.5px; font-weight: 600; padding: 2px 8px; + border-radius: 5px; letter-spacing: 0.4px; text-transform: uppercase; +} +.tag-approval { background: rgba(217,119,6,0.14); color: #f5b755; border: 1px solid rgba(217,119,6,0.3); } +.tag-agent { background: rgba(59,130,246,0.14); color: #7eb0ff; border: 1px solid rgba(59,130,246,0.3); } +.tag-input { background: rgba(94,108,138,0.16); color: var(--text-2); border: 1px solid var(--border-strong); } +.tag-live { background: rgba(52,211,153,0.16); color: var(--ok); border: 1px solid rgba(52,211,153,0.4); } +.tag-syn { background: rgba(168,85,247,0.16); color: var(--syn); border: 1px solid rgba(168,85,247,0.4); } + +.pill { + display: inline-flex; align-items: center; + font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 5px; + border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text-2); +} +.pill-done { background: rgba(52,211,153,0.16); color: var(--ok); border-color: rgba(52,211,153,0.36); } +.pill-running { background: rgba(59,130,246,0.16); color: #7eb0ff; border-color: rgba(59,130,246,0.36); } +.pill-errored { background: rgba(240,82,82,0.16); color: var(--block); border-color: rgba(240,82,82,0.4); } +.pill-queued { background: rgba(217,119,6,0.14); color: #f5b755; border-color: rgba(217,119,6,0.36); } +.pill-blocked { background: rgba(240,82,82,0.14); color: var(--block); border-color: rgba(240,82,82,0.4); } +.pill-idle { background: var(--surface-2); color: var(--text-2); } + +.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; display: inline-block; } +.dot-done { background: var(--ok); } +.dot-running { background: var(--run); box-shadow: 0 0 8px var(--run); animation: pulse 1.6s ease-in-out infinite; } +.dot-queued { background: var(--queue); } +.dot-errored, .dot-blocked { background: var(--block); } +.dot-idle { background: var(--idle); } +@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } } +@media (prefers-reduced-motion: reduce) { .dot-running { animation: none; } * { transition: none !important; animation: none !important; } } + +/* ===================================================================== + Buttons + ===================================================================== */ +.btn { + display: inline-flex; align-items: center; justify-content: center; gap: 7px; + padding: 7px 11px; border-radius: 8px; font-size: 12px; font-weight: 600; + border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text); + transition: background .15s, border-color .15s, transform .15s; +} +.btn:hover:not(:disabled) { border-color: var(--primary); background: var(--surface-3); } +.btn:disabled { opacity: 0.5; cursor: not-allowed; } +.btn-primary { background: linear-gradient(180deg, #3b82f6, #2563eb); border-color: var(--primary); color: #fff; } +.btn-primary:hover:not(:disabled) { background: linear-gradient(180deg, #4d8df8, #2f6cee); } +.btn-ghost { background: transparent; } +.btn-lg { padding: 11px 18px; font-size: 14px; } + +/* ===================================================================== + Process graph + ===================================================================== */ +.graph-canvas { position: relative; width: 100%; height: 100%; min-height: 0; } +.graph-overlay { + position: absolute; top: 14px; left: 14px; z-index: 4; + background: rgba(15,22,38,0.78); backdrop-filter: blur(8px); + border: 1px solid var(--border); border-radius: 10px; padding: 6px 10px; + font-size: 12px; color: var(--text-2); +} +.graph-overlay-row { display: inline-flex; align-items: center; gap: 8px; } +.graph-overlay-name { color: var(--text); font-weight: 600; } +.graph-overlay-sub { color: var(--text-2); } +.graph-overlay-dim { color: var(--text-3); font-family: var(--mono); font-size: 11px; } + +.node { + width: 256px; min-width: 256px; max-width: 256px; + background: linear-gradient(180deg, rgba(21,30,51,0.92), rgba(15,22,38,0.92)); + backdrop-filter: blur(6px); + border: 1px solid var(--border); + border-radius: 12px; + padding: 10px 12px; + color: var(--text); + transition: border-color .18s, box-shadow .18s, transform .18s; +} +.node:hover { border-color: var(--border-strong); } +.node-sel { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary) inset, 0 12px 28px rgba(59,130,246,0.22); } +.node-row { display: flex; align-items: center; gap: 8px; } +.node-name { font-weight: 600; font-size: 13px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.node-meta { display: flex; align-items: center; gap: 8px; margin-top: 8px; color: var(--text-2); font-size: 11px; } +.node-kind { + font-size: 9.5px; letter-spacing: 0.6px; text-transform: uppercase; + border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; color: var(--text-3); +} +.node-kind-human { color: #c8b6ff; border-color: rgba(168,85,247,0.4); } +.node-kind-agent { color: #7eb0ff; border-color: rgba(59,130,246,0.4); } +.node-kind-service { color: #5eead4; border-color: rgba(20,184,166,0.4); } +.node-kind-start, .node-kind-end { color: #fef3c7; border-color: rgba(217,119,6,0.4); } +.node-owner { color: var(--text-2); } +.node-gov { display: inline-flex; align-items: center; gap: 3px; color: #f5b755; } +.node-handle { background: var(--border-strong); width: 8px; height: 8px; border: 0; } + +.node-dot { width: 8px; height: 8px; border-radius: 50%; } +.node-dot-done { background: var(--ok); } +.node-dot-running { background: var(--run); box-shadow: 0 0 8px var(--run); animation: pulse 1.6s ease-in-out infinite; } +.node-dot-queued { background: var(--queue); } +.node-dot-errored, .node-dot-blocked { background: var(--block); } +.node-dot-idle { background: var(--idle); } + +.node-running { + box-shadow: 0 0 0 1px var(--run) inset, 0 8px 36px rgba(59,130,246,0.22); + border-color: var(--run); +} +.node-errored { + box-shadow: 0 0 0 1px var(--block) inset; + border-color: var(--block); +} +.node-done { opacity: 0.85; } + +/* ReactFlow style overrides */ +.react-flow__controls { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; } +.react-flow__controls-button { background: var(--surface); border-bottom: 1px solid var(--border); color: var(--text-2); } +.react-flow__controls-button:hover { background: var(--surface-2); color: var(--text); } +.react-flow__attribution { display: none; } + +/* ===================================================================== + Inspector + ===================================================================== */ +.inspector { + border-left: 1px solid var(--border); + background: var(--bg-deep); + display: flex; flex-direction: column; + min-height: 0; +} +.inspector-head { padding: 14px 14px 10px; border-bottom: 1px solid var(--border); } +.inspector-eyebrow { color: var(--text-3); font-size: 10px; text-transform: uppercase; letter-spacing: 1.1px; font-weight: 600; } +.inspector-title h3 { margin: 4px 0 6px; font-size: 16px; font-weight: 700; } +.inspector-sub { color: var(--text-2); font-size: 12px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } +.inspector-tabs { display: flex; gap: 3px; margin-top: 12px; background: var(--surface-2); padding: 3px; border-radius: 8px; border: 1px solid var(--border); } +.itab { + flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 4px; + padding: 5px 6px; border-radius: 6px; font-size: 11px; + color: var(--text-2); transition: color .15s, background .15s; +} +.itab:hover { color: var(--text); } +.itab-sel { background: var(--surface); color: var(--text); box-shadow: 0 0 0 1px var(--border-strong) inset; } +.inspector-body { padding: 12px 14px 18px; overflow-y: auto; flex: 1; min-height: 0; } + +.i-section { display: flex; flex-direction: column; gap: 6px; } +.i-field { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px dashed var(--border); font-size: 13px; } +.i-field span:first-child { color: var(--text-2); } +.i-field span:last-child { text-align: right; } +.i-h { margin: 14px 0 6px; font-size: 11px; letter-spacing: 1px; text-transform: uppercase; color: var(--text-3); font-weight: 700; } +.i-actions { display: flex; gap: 8px; flex-wrap: wrap; } + +.rule { background: var(--surface); border: 1px solid var(--border); border-left: 2px solid var(--accent); border-radius: 8px; padding: 9px 11px; } +.rule-head { display: flex; align-items: center; gap: 7px; color: var(--text); font-weight: 600; font-size: 12.5px; } +.rule-expr { color: var(--text-2); font-size: 12px; margin-top: 5px; } + +.evt { display: flex; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--border); } +.evt-ts { color: var(--text-3); font-size: 11px; min-width: 48px; } +.evt-who { color: #7eb0ff; font-size: 11px; } +.evt-sum { font-size: 12.5px; margin-top: 2px; color: var(--text-soft); } + +.run { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 9px 11px; } +.run-head { display: flex; align-items: center; gap: 8px; } +.run-step { color: var(--text-2); font-size: 12px; margin-left: auto; } +.run-sub { color: var(--text-3); font-size: 11px; margin-top: 4px; } + +.raw-json { + margin: 0; padding: 12px; border-radius: 8px; + background: var(--surface); border: 1px solid var(--border); + color: var(--text-2); font-family: var(--mono); font-size: 11.5px; + line-height: 1.5; overflow-x: auto; max-height: 60vh; +} +.empty { color: var(--text-3); font-size: 12.5px; padding: 18px 2px; text-align: center; } + +/* ===================================================================== + Telemetry strip + ===================================================================== */ +.telemetry { + display: flex; align-items: center; gap: 18px; + padding: 8px 18px; border-top: 1px solid var(--border); + background: linear-gradient(0deg, var(--surface) 0%, var(--bg) 100%); + min-height: 44px; font-size: 12px; color: var(--text-2); +} +.t-block { display: inline-flex; align-items: center; gap: 7px; } +.t-eyebrow { color: var(--text-3); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.8px; display: inline-flex; align-items: center; gap: 4px; } +.t-v { color: var(--text); font-weight: 600; font-size: 13px; } +.t-divider { width: 1px; height: 22px; background: var(--border); } +.t-spacer { flex: 1; } +.spark { display: block; } +.gauge { background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px; overflow: hidden; } +.gauge-fill { height: 100%; transition: width .35s ease; } +.t-tick { width: 8px; height: 8px; border-radius: 50%; background: var(--run); box-shadow: 0 0 10px var(--run); animation: pulse 1.6s ease-in-out infinite; } + +/* ===================================================================== + Command palette + ===================================================================== */ +.cmd-overlay { + position: fixed; inset: 0; background: rgba(3,5,11,0.6); + display: flex; align-items: flex-start; justify-content: center; + padding-top: 12vh; z-index: 200; +} +.cmd { + width: min(620px, 92vw); + background: var(--surface); + border: 1px solid var(--border-strong); + border-radius: 14px; + overflow: hidden; + box-shadow: 0 30px 80px rgba(0,0,0,0.7); +} +.cmd-input-row { display: flex; align-items: center; gap: 9px; padding: 13px 16px; border-bottom: 1px solid var(--border); color: var(--text-2); } +.cmd-input-row [cmdk-input] { flex: 1; border: 0; outline: 0; background: transparent; color: var(--text); font-size: 14.5px; font-family: var(--sans); } +.kbd-hint { font-size: 10.5px; } +.cmd [cmdk-list] { max-height: 380px; overflow: auto; padding: 8px; } +.cmd [cmdk-group-heading] { color: var(--text-3); font-size: 10.5px; text-transform: uppercase; letter-spacing: 1px; padding: 8px 10px 4px; font-weight: 700; } +.cmd [cmdk-item] { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 8px; color: var(--text); cursor: pointer; font-size: 13px; } +.cmd [cmdk-item][data-selected='true'] { background: var(--surface-2); box-shadow: 0 0 0 1px var(--primary) inset; } +.cmd-hint { margin-left: auto; color: var(--text-3); font-size: 11px; } +.cmd [cmdk-empty] { padding: 24px; text-align: center; color: var(--text-3); font-size: 13px; } + +/* ===================================================================== + Tour + ===================================================================== */ +.tour-card { + position: fixed; z-index: 250; + width: min(340px, 92vw); + background: linear-gradient(180deg, var(--surface) 0%, var(--bg-deep) 100%); + border: 1px solid var(--border-strong); + border-radius: 14px; + padding: 14px 16px 13px; + box-shadow: 0 26px 80px rgba(0,0,0,0.6), 0 0 0 1px var(--border-glow); +} +.tour-anchor-graph { left: calc(320px + 32px); bottom: 86px; } +.tour-anchor-queue { left: 24px; bottom: 86px; } +.tour-anchor-inspector { right: 24px; bottom: 86px; } +.tour-anchor-topbar { right: 24px; top: 76px; } +.tour-anchor-command { right: 24px; top: 76px; } +.tour-anchor-telemetry { left: 50%; transform: translateX(-50%); bottom: 64px; } + +.tour-head { display: flex; align-items: center; gap: 7px; color: var(--text-2); } +.tour-eyebrow { color: var(--text-3); font-size: 11px; text-transform: uppercase; letter-spacing: 1px; } +.tour-close { margin-left: auto; padding: 4px; border-radius: 6px; color: var(--text-3); transition: color .15s, background .15s; } +.tour-close:hover { color: var(--text); background: var(--surface-2); } +.tour-title { margin: 8px 0 6px; font-size: 16px; font-weight: 700; letter-spacing: -0.2px; } +.tour-body { color: var(--text-2); font-size: 13px; margin: 0 0 12px; } +.tour-actions { display: flex; gap: 8px; } +.tour-actions .btn { flex: 1; } + +/* ===================================================================== + Landing + ===================================================================== */ +.landing { position: relative; height: 100%; min-height: 100vh; display: grid; grid-template-rows: auto 1fr auto; overflow-y: auto; } +.landing-bg { + position: absolute; inset: 0; + background: + radial-gradient(circle at 12% 18%, rgba(59,130,246,0.22) 0%, transparent 40%), + radial-gradient(circle at 86% 76%, rgba(168,85,247,0.18) 0%, transparent 45%), + radial-gradient(circle at 60% 5%, rgba(20,184,166,0.10) 0%, transparent 35%), + var(--bg); + z-index: 0; +} +.landing-grid { + position: absolute; inset: 0; z-index: 0; + background: + linear-gradient(to right, rgba(255,255,255,0.025) 1px, transparent 1px) 0 0/72px 72px, + linear-gradient(to bottom, rgba(255,255,255,0.025) 1px, transparent 1px) 0 0/72px 72px; + mask-image: radial-gradient(circle at 50% 40%, black 0%, transparent 70%); +} +.landing-top { + position: relative; z-index: 2; + display: flex; align-items: center; justify-content: space-between; + padding: 22px 32px; +} +.landing-main { + position: relative; z-index: 1; + padding: 30px 32px 60px; + max-width: 1200px; margin: 0 auto; width: 100%; + display: grid; gap: 36px; +} +.landing-hero { display: flex; flex-direction: column; gap: 14px; max-width: 760px; } +.hero-eyebrow { + display: inline-flex; align-items: center; gap: 7px; + font-size: 11.5px; color: var(--text-2); padding: 5px 10px; border-radius: 999px; + border: 1px solid var(--border-strong); background: rgba(15,22,38,0.6); backdrop-filter: blur(6px); + width: max-content; +} +.hero-title { + font-size: clamp(38px, 5vw, 60px); + line-height: 1.05; + margin: 4px 0 2px; + font-weight: 800; + letter-spacing: -1.4px; +} +.hl { + background: linear-gradient(90deg, #7eb0ff 0%, #c8b6ff 60%, #5eead4 100%); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} +.hero-sub { color: var(--text-2); font-size: 16.5px; max-width: 640px; } +.hero-actions { display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap; } +.hero-stats { + display: flex; gap: 22px; margin-top: 18px; padding-top: 18px; + border-top: 1px solid var(--border); + flex-wrap: wrap; +} +.stat { display: inline-flex; align-items: baseline; gap: 7px; } +.stat-v { font-size: 22px; font-weight: 700; } +.stat-l { color: var(--text-3); font-size: 12px; text-transform: uppercase; letter-spacing: 0.8px; } + +.landing-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 14px; +} +.sc-card { + display: flex; flex-direction: column; gap: 6px; text-align: left; + background: linear-gradient(180deg, rgba(21,30,51,0.86), rgba(15,22,38,0.86)); + border: 1px solid var(--border); + border-radius: 14px; + padding: 16px 16px 14px; + color: var(--text); + position: relative; + transition: transform .18s, border-color .18s, box-shadow .18s; + overflow: hidden; +} +.sc-card::before { + content: ""; position: absolute; inset: 0; + background: radial-gradient(circle at 0 0, var(--sc-accent, var(--primary)) 0%, transparent 60%); + opacity: 0.08; pointer-events: none; +} +.sc-card:hover { transform: translateY(-3px); border-color: var(--sc-accent, var(--primary)); box-shadow: 0 18px 50px rgba(0,0,0,0.45); } +.sc-card-top { display: flex; align-items: center; gap: 8px; } +.sc-card-mark { width: 16px; height: 16px; border-radius: 5px; background: var(--sc-accent, var(--primary)); box-shadow: 0 0 14px var(--sc-accent, var(--primary)); } +.sc-card-title { margin: 4px 0 2px; font-size: 17px; font-weight: 700; letter-spacing: -0.2px; } +.sc-card-sub { color: var(--text-2); font-size: 12.5px; margin: 0 0 10px; } +.sc-card-meta { color: var(--text-3); font-size: 11.5px; display: inline-flex; gap: 6px; } +.sc-card-cta { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; color: var(--sc-accent, var(--primary)); font-weight: 600; font-size: 12px; } + +.landing-foot { position: relative; z-index: 1; padding: 14px 32px; border-top: 1px solid var(--border); color: var(--text-3); font-size: 11.5px; text-align: center; } +.foot-eyebrow { letter-spacing: 0.6px; } + +/* ===================================================================== + RunHistory + ===================================================================== */ +.rh { height: 100%; display: flex; flex-direction: column; min-height: 0; } +.rh-head { display: flex; align-items: end; justify-content: space-between; padding: 18px 24px; gap: 12px; border-bottom: 1px solid var(--border); background: var(--bg); } +.rh-filters { display: inline-flex; gap: 6px; } +.rh-chip { + padding: 5px 11px; border-radius: 999px; font-size: 12px; + border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text-2); + text-transform: capitalize; +} +.rh-chip:hover { color: var(--text); border-color: var(--primary); } +.rh-chip-sel { background: var(--primary-deep); border-color: var(--primary); color: #fff; } + +.rh-list { overflow-y: auto; padding: 8px 16px 24px; display: flex; flex-direction: column; gap: 4px; } +.rh-row { + display: grid; grid-template-columns: 200px 180px minmax(0, 1.3fr) minmax(160px, 1fr) auto; + align-items: center; gap: 14px; + padding: 10px 14px; border-radius: 10px; + border: 1px solid transparent; + font-size: 13px; color: var(--text); +} +.rh-row:hover { background: var(--surface-2); border-color: var(--border); } +.rh-row-id { display: inline-flex; align-items: center; gap: 8px; min-width: 0; } +.rh-row-id .mono { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; } +.rh-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; } +.rh-row-scenario { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; } +.rh-row-step { color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; } +.rh-row-bar { background: var(--surface-2); border-radius: 999px; height: 8px; overflow: hidden; border: 1px solid var(--border); } +.rh-bar-fill { height: 100%; transition: width .3s ease; } +.rh-row-meta { display: inline-flex; align-items: center; gap: 8px; color: var(--text-2); } + +/* Scrollbar */ +.scene ::-webkit-scrollbar, .left-rail::-webkit-scrollbar, .inspector-body::-webkit-scrollbar, .rh-list::-webkit-scrollbar, .cmd [cmdk-list]::-webkit-scrollbar, .landing::-webkit-scrollbar { + width: 8px; height: 8px; +} +.scene ::-webkit-scrollbar-thumb, .left-rail::-webkit-scrollbar-thumb, .inspector-body::-webkit-scrollbar-thumb, .rh-list::-webkit-scrollbar-thumb, .cmd [cmdk-list]::-webkit-scrollbar-thumb, .landing::-webkit-scrollbar-thumb { + background: var(--border-strong); border-radius: 4px; +} +.scene ::-webkit-scrollbar-track, .left-rail::-webkit-scrollbar-track, .inspector-body::-webkit-scrollbar-track, .rh-list::-webkit-scrollbar-track, .cmd [cmdk-list]::-webkit-scrollbar-track, .landing::-webkit-scrollbar-track { + background: transparent; +} + +/* ===================================================================== + Live-mode pill / toggle / banners (added in v2 honesty pass) + ===================================================================== */ +.mode-pill { + display: inline-flex; align-items: center; + font-size: 10px; font-weight: 700; letter-spacing: 0.8px; + padding: 2px 8px; border-radius: 5px; text-transform: uppercase; +} +.mode-snapshot { background: rgba(168,85,247,0.16); color: var(--syn); border: 1px solid rgba(168,85,247,0.4); } +.mode-live { background: rgba(52,211,153,0.18); color: var(--ok); border: 1px solid rgba(52,211,153,0.45); } + +.mode-toggle { gap: 8px; } +.mode-toggle.mode-live { border-color: rgba(52,211,153,0.45); } +.topbar-age { font-family: var(--mono); font-size: 10.5px; color: var(--text-3); margin-left: 2px; } + +.spin { + width: 12px; height: 12px; border-radius: 50%; + border: 2px solid var(--border-strong); border-top-color: var(--primary); + animation: spin 0.8s linear infinite; display: inline-block; +} +@keyframes spin { to { transform: rotate(360deg); } } +@media (prefers-reduced-motion: reduce) { .spin { animation: none; } } + +.mc-banner { + display: flex; align-items: center; gap: 9px; + padding: 8px 18px; font-size: 12.5px; + border-bottom: 1px solid var(--border); +} +.mc-banner-info { background: rgba(59,130,246,0.08); color: #7eb0ff; } +.mc-banner-err { background: rgba(240,82,82,0.10); color: #ff8a8a; } +.mc-banner .mono { font-size: 12px; color: inherit; } + +.preview-marker { + display: inline-block; + margin-left: 6px; padding: 0 6px; + font-size: 9.5px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; + border: 1px solid rgba(168,85,247,0.45); color: var(--syn); + background: rgba(168,85,247,0.12); + border-radius: 4px; +} + +.btn-decline { color: #ff9b9b; } +.btn-decline:hover:not(:disabled) { border-color: var(--block); } + +.is-on { border-color: var(--ok); color: var(--ok); } + +/* ===================================================================== + Toaster + ===================================================================== */ +.toaster { + position: fixed; right: 18px; bottom: 18px; z-index: 300; + display: flex; flex-direction: column; gap: 8px; + width: min(380px, 92vw); pointer-events: none; +} +.toast { + pointer-events: auto; + display: flex; align-items: center; gap: 9px; + padding: 10px 12px; border-radius: 10px; + background: var(--surface-2); border: 1px solid var(--border-strong); + box-shadow: 0 16px 50px rgba(0,0,0,0.45); + font-size: 12.5px; color: var(--text); +} +.toast-msg { flex: 1; line-height: 1.4; } +.toast-x { padding: 2px; color: var(--text-3); border-radius: 5px; } +.toast-x:hover { color: var(--text); background: var(--surface-3); } +.toast-info { border-left: 3px solid var(--primary); } +.toast-ok { border-left: 3px solid var(--ok); } +.toast-warn { border-left: 3px solid var(--queue); } +.toast-err { border-left: 3px solid var(--block); } diff --git a/src/lib/api.test.ts b/src/lib/api.test.ts new file mode 100644 index 0000000..a4f09ac --- /dev/null +++ b/src/lib/api.test.ts @@ -0,0 +1,108 @@ +// Tests the in-browser API client against a stubbed fetch. +// We don't hit the real backend here — that's covered by the smoke test +// (`pnpm qa:smoke` toggles live mode and asserts the network call resolves). +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { api } from "./api"; + +function mockFetch(handlers: Array<(url: string, init: RequestInit) => Response | undefined>) { + const calls: Array<{ url: string; init: RequestInit }> = []; + globalThis.fetch = vi.fn(async (input: RequestInfo | URL, init: RequestInit = {}) => { + const url = typeof input === "string" ? input : input.toString(); + calls.push({ url, init }); + for (const h of handlers) { + const r = h(url, init); + if (r) return r; + } + return new Response("not stubbed", { status: 500 }); + }) as unknown as typeof fetch; + // sessionStorage stub + const store = new Map(); + globalThis.sessionStorage = { + getItem: (k) => store.get(k) ?? null, + setItem: (k, v) => { store.set(k, String(v)); }, + removeItem: (k) => { store.delete(k); }, + clear: () => store.clear(), + key: () => null, + length: 0, + } as Storage; + return calls; +} + +beforeEach(() => { + // reset between tests + api.clearToken(); +}); + +describe("api client", () => { + it("ping() returns ok with email on success", async () => { + mockFetch([ + (url) => url.endsWith("/api/v1/auth/dev-login") + ? new Response(JSON.stringify({ access_token: "T1" }), { status: 200, headers: { "Content-Type": "application/json" } }) + : undefined, + (url) => url.endsWith("/api/v1/auth/me") + ? new Response(JSON.stringify({ user_id: "u1", tenant_id: "t1", email: "dev@flow-master.ai" }), { status: 200, headers: { "Content-Type": "application/json" } }) + : undefined, + ]); + const r = await api.ping(); + expect(r.ok).toBe(true); + expect(r.user).toBe("dev@flow-master.ai"); + }); + + it("ping() returns ok=false with reason when login fails", async () => { + mockFetch([ + (url) => url.endsWith("/api/v1/auth/dev-login") + ? new Response("nope", { status: 401 }) + : undefined, + ]); + const r = await api.ping(); + expect(r.ok).toBe(false); + expect(r.reason).toMatch(/401/); + }); + + it("workItems() returns the items array", async () => { + mockFetch([ + (url) => url.endsWith("/api/v1/auth/dev-login") + ? new Response(JSON.stringify({ access_token: "T2" }), { status: 200 }) + : undefined, + (url) => url.includes("/api/ea2/work-items") + ? new Response(JSON.stringify({ items: [{ transaction_id: "tx1", status: "running", definition_key: "k1" }] }), { status: 200 }) + : undefined, + ]); + const items = await api.workItems(); + expect(items.length).toBe(1); + expect(items[0].transaction_id).toBe("tx1"); + }); + + it("graph() returns null on 404 (typed-safe failure mode)", async () => { + mockFetch([ + (url) => url.endsWith("/api/v1/auth/dev-login") + ? new Response(JSON.stringify({ access_token: "T3" }), { status: 200 }) + : undefined, + (url) => url.includes("/api/ea2/process-definitions/") + ? new Response("not found", { status: 404 }) + : undefined, + ]); + const g = await api.graph("does-not-exist"); + expect(g).toBeNull(); + }); + + it("re-logs in after 401 then succeeds", async () => { + let metHits = 0; + const calls = mockFetch([ + (url) => url.endsWith("/api/v1/auth/dev-login") + ? new Response(JSON.stringify({ access_token: `T${metHits + 1}` }), { status: 200 }) + : undefined, + (url) => { + if (url.endsWith("/api/v1/auth/me")) { + metHits += 1; + if (metHits === 1) return new Response("expired", { status: 401 }); + return new Response(JSON.stringify({ user_id: "u", tenant_id: "t", email: "dev@flow-master.ai" }), { status: 200 }); + } + return undefined; + }, + ]); + const r = await api.ping(); + expect(r.ok).toBe(true); + expect(calls.filter((c) => c.url.endsWith("/dev-login")).length).toBe(2); // initial + retry login + }); +}); diff --git a/src/lib/api.ts b/src/lib/api.ts new file mode 100644 index 0000000..148dc4f --- /dev/null +++ b/src/lib/api.ts @@ -0,0 +1,174 @@ +// Real in-browser API client for demo.flow-master.ai. +// - dev-login → bearer (cached in sessionStorage, refresh on 401) +// - typed wrappers for the endpoints Mission Control needs +// - all fetches honor an AbortSignal so unmounts cancel cleanly +// - never throws into render: returns { ok, error } shapes + +export interface ApiConfig { + baseUrl: string; + email: string; +} + +// In dev, route via vite proxy (same-origin) to dodge CORS; in production +// the build is deployed at the same origin as the backend, so an empty +// baseUrl is correct. +const isDev = import.meta.env.DEV; +const DEFAULT_CONFIG: ApiConfig = { + baseUrl: import.meta.env.VITE_FM_BASE || (isDev ? "" : "https://demo.flow-master.ai"), + email: import.meta.env.VITE_FM_EMAIL || "dev@flow-master.ai", +}; + +const TOKEN_KEY = "fm.mc.token.v1"; + +let inflightLogin: Promise | null = null; + +async function login(cfg: ApiConfig, signal?: AbortSignal): Promise { + if (inflightLogin) return inflightLogin; + inflightLogin = (async () => { + const r = await fetch(`${cfg.baseUrl}/api/v1/auth/dev-login`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ email: cfg.email }), + signal, + }); + if (!r.ok) throw new Error(`dev-login ${r.status}`); + const body = (await r.json()) as { access_token: string }; + sessionStorage.setItem(TOKEN_KEY, body.access_token); + return body.access_token; + })(); + try { + return await inflightLogin; + } finally { + inflightLogin = null; + } +} + +async function withAuth( + cfg: ApiConfig, + path: string, + init: RequestInit = {}, + signal?: AbortSignal, +): Promise { + let token = sessionStorage.getItem(TOKEN_KEY); + if (!token) token = await login(cfg, signal); + const doFetch = async () => + fetch(`${cfg.baseUrl}${path}`, { + ...init, + headers: { + ...(init.headers || {}), + Authorization: `Bearer ${token}`, + Accept: "application/json", + }, + signal, + }); + let r = await doFetch(); + if (r.status === 401) { + sessionStorage.removeItem(TOKEN_KEY); + token = await login(cfg, signal); + r = await doFetch(); + } + if (!r.ok) { + const text = await r.text().catch(() => ""); + throw new Error(`${path} → ${r.status} ${text.slice(0, 120)}`); + } + return (await r.json()) as T; +} + +export interface WorkItem { + transaction_id: string; + short_id?: string; + status: string; + hub?: string; + age_days?: number; + active_step_display_name?: string; + current_node?: string; + next_action?: string; + definition_key: string; + business_subject?: string; + created_at?: string; +} + +export interface ProcessGraph { + process_definition: { + _key: string; + name: string; + display_name?: string; + hub?: string; + config: { nodes: unknown[]; edges: unknown[]; org_id?: string }; + }; + version_definitions?: Array<{ version: number; approved_at?: string }>; +} + +export interface RuntimeTransaction { + transaction_id: string; + status: string; + active_step?: { step_definition_id?: string; display_name?: string }; + available_actions?: Array<{ display_label: string }>; + created_at?: string; + business_subject?: string; +} + +export interface AuthMe { + user_id: string; + tenant_id: string; + email: string; + display_name?: string; +} + +export const api = { + config: DEFAULT_CONFIG, + + async me(signal?: AbortSignal): Promise { + return withAuth(this.config, "/api/v1/auth/me", {}, signal); + }, + + async workItems(signal?: AbortSignal): Promise { + const body = await withAuth<{ items?: WorkItem[] }>( + this.config, + "/api/ea2/work-items?view=all", + {}, + signal, + ); + return body.items ?? []; + }, + + async graph(defKey: string, signal?: AbortSignal): Promise { + try { + return await withAuth( + this.config, + `/api/ea2/process-definitions/${defKey}/graph`, + {}, + signal, + ); + } catch { + return null; + } + }, + + async transaction(txId: string, signal?: AbortSignal): Promise { + try { + return await withAuth( + this.config, + `/api/runtime/transactions/${txId}`, + {}, + signal, + ); + } catch { + return null; + } + }, + + /** Probe whether the backend is reachable. Never throws. */ + async ping(signal?: AbortSignal): Promise<{ ok: boolean; reason?: string; user?: string }> { + try { + const me = await this.me(signal); + return { ok: true, user: me.email }; + } catch (e) { + return { ok: false, reason: (e as Error).message }; + } + }, + + clearToken() { + sessionStorage.removeItem(TOKEN_KEY); + }, +}; diff --git a/src/lib/buildScenarios.ts b/src/lib/buildScenarios.ts new file mode 100644 index 0000000..d346930 --- /dev/null +++ b/src/lib/buildScenarios.ts @@ -0,0 +1,312 @@ +// In-browser equivalent of fetch_scenarios.mjs: +// pulls live work items → groups by definition_key → fetches each graph and +// representative runtime → maps into ProcessScenario[] using the same shape +// as the bundled snapshot loader (`data/live.ts`). +import { api, type WorkItem, type ProcessGraph, type RuntimeTransaction } from "./api"; +import type { + AgentRun, EvidenceItem, FlowEdge, ProcessScenario, ProcessStep, + QueueItem, Rule, RuntimeState, RunSummary, StepAction, StepKind, TourStep, +} from "../data/types"; + +const KIND_FROM_TYPE: Record = { + start: "start", + end: "end", + human_task: "human", + agent_task: "agent", + service_task: "service", + system_task: "service", +}; +const OWNER_FROM_TYPE: Record = { + start: "system", + end: "system", + human_task: "human", + agent_task: "agent", + service_task: "system", + system_task: "system", +}; +const WAIT_FROM_STATUS: Record = { + running: "approval", + waiting_for_user: "approval", + waiting_for_agent: "agent", + errored: "input", + failed: "input", +}; + +const shortNode = (defKey: string, id: string | null | undefined): string | null => + id ? id.replace(`${defKey}_`, "") : null; + +interface LiveNode { + id: string; + type: string; + label?: string; + display_name?: string; + actions?: Array<{ id: string; display_label?: string; label?: string; kind: string }>; +} +interface LiveEdge { + id: string; + source: string; + target: string; + outcome?: string; +} + +function buildScenarioFromGraph( + family: ProcessScenario["family"], + defKey: string, + graph: ProcessGraph, + cases: WorkItem[], + headlineRt: RuntimeTransaction | null, + recent: RuntimeTransaction[], +): ProcessScenario { + const pd = graph.process_definition; + const cfg = pd.config as { nodes: LiveNode[]; edges: LiveEdge[] }; + const activeNode = headlineRt ? shortNode(defKey, headlineRt.active_step?.step_definition_id) : null; + const activeIdx = cfg.nodes.findIndex((n) => n.id === activeNode); + const rtStatus = headlineRt?.status ?? "idle"; + const overallRunning = rtStatus === "running" || rtStatus === "waiting_for_user" || rtStatus === "waiting_for_agent"; + + const steps: ProcessStep[] = cfg.nodes.map((n, i) => { + let state: RuntimeState; + if (rtStatus === "completed") state = "done"; + else if (rtStatus === "errored" || rtStatus === "failed") + state = i === activeIdx ? "errored" : i < activeIdx ? "done" : "idle"; + else if (overallRunning) { + if (n.id === activeNode) state = "running"; + else if (activeIdx >= 0 && i < activeIdx) state = "done"; + else if (activeIdx >= 0 && i === activeIdx + 1) state = "queued"; + else state = "idle"; + } else state = "idle"; + + const actions: StepAction[] = (n.actions || []).map((a) => ({ + id: a.id, + label: a.display_label || a.label || a.kind, + kind: (a.kind === "approve" || a.kind === "decline" || a.kind === "fork" ? a.kind : "complete") as StepAction["kind"], + })); + return { + id: n.id, + name: n.label || n.display_name || n.id, + kind: KIND_FROM_TYPE[n.type] || "service", + owner: OWNER_FROM_TYPE[n.type] || "human", + governs: n.type === "human_task" ? ["spend-threshold"] : [], + state, + actions, + raw: n, + }; + }); + + const stepById = new Map(steps.map((s) => [s.id, s])); + const edges: FlowEdge[] = cfg.edges.map((e) => ({ + id: e.id, + source: e.source, + target: e.target, + label: e.outcome, + traversed: stepById.get(e.source)?.state === "done", + })); + + const rules: Rule[] = steps.some((s) => s.governs.length) + ? [{ id: "spend-threshold", name: "Spend threshold", expr: "amount > 10_000 → dual approval", isSynthetic: true }] + : []; + + const evidence: EvidenceItem[] = activeNode + ? [ + { + id: "ev-rt", + stepId: activeNode, + at: (headlineRt?.created_at || "").slice(11, 16) || "now", + actor: "runtime", + summary: `Transaction ${headlineRt?.transaction_id?.slice(0, 8)} active at ${headlineRt?.active_step?.display_name ?? activeNode}`, + }, + ] + : []; + + const queue: QueueItem[] = cases.slice(0, 8).map((c, i) => ({ + id: `${c.transaction_id || defKey}-${i}`, + stepId: shortNode(defKey, c.current_node) || activeNode || steps[0]?.id || "", + title: `${c.short_id ?? c.transaction_id?.slice(0, 8) ?? "case"} · ${c.active_step_display_name || c.next_action || "case"}`, + waitingOn: WAIT_FROM_STATUS[c.status] ?? "input", + ageDays: c.age_days ?? 0, + status: c.status, + })); + + const agentRuns: AgentRun[] = activeNode + ? [ + { + id: "agent-1", + stepId: activeNode, + status: "awaiting-confirm", + intent: `Action "${headlineRt?.available_actions?.[0]?.display_label ?? "Complete"}" via sidekick_on_behalf_of_user`, + isSynthetic: true, + }, + ] + : []; + + const seenRunIds = new Set(); + const runs: RunSummary[] = [headlineRt, ...recent].filter(Boolean).flatMap((rt) => { + const r = rt as RuntimeTransaction; + if (seenRunIds.has(r.transaction_id)) return []; + seenRunIds.add(r.transaction_id); + const started = r.created_at ? new Date(r.created_at).getTime() : Date.now(); + return [{ + id: r.transaction_id, + shortId: r.transaction_id.slice(0, 8), + activeStep: r.active_step?.display_name ?? null, + status: r.status, + startedAt: r.created_at ?? "", + durationSec: Math.max(60, Math.floor((Date.now() - started) / 1000)), + }]; + }); + + const statuses: Record = {}; + for (const c of cases) statuses[c.status] = (statuses[c.status] || 0) + 1; + + const kpis = [ + { label: "Live cases", value: String(cases.length), trend: "up" as const, trendValue: `${Math.min(3, cases.length)} now` }, + { label: "Running", value: String(statuses.running ?? 0), trend: "flat" as const }, + { label: "Errored", value: String((statuses.errored ?? 0) + (statuses.failed ?? 0)), trend: (statuses.errored ?? 0) > 0 ? ("up" as const) : ("flat" as const) }, + { label: "Avg cycle", value: avgCycle(cases), trend: "down" as const, trendValue: "" }, + ]; + + const defaultStepId = activeNode || steps[0]?.id || ""; + const versionLabel = `v${graph.version_definitions?.[0]?.version ?? 1}`; + + return { + id: family.id, + family, + live: true, + defKey, + defName: pd.display_name || pd.name, + version: versionLabel, + headlineTx: headlineRt?.transaction_id ?? null, + tagline: `${pd.display_name || pd.name} · ${versionLabel} · live from demo.flow-master.ai`, + steps, + edges, + rules, + evidence, + queue, + agentRuns, + runs, + kpis, + defaultStepId, + tour: buildTour(family.id, defaultStepId), + raw: { graph, headlineRt }, + }; +} + +function avgCycle(cases: WorkItem[]): string { + const ages = cases.map((c) => c.age_days ?? 0).filter((a) => a > 0); + if (!ages.length) return "—"; + const avg = ages.reduce((s, a) => s + a, 0) / ages.length; + return `${avg.toFixed(1)}d`; +} + +function buildTour(familyId: string, defaultStepId: string): TourStep[] { + return [ + { id: "t1", anchor: "graph", title: "Live process at a glance", body: "This graph is the real, executing definition for this scenario. Each node maps to a runtime step the backend is driving.", selectStep: defaultStepId }, + { id: "t2", anchor: "queue", title: "Real cases, real states", body: "The left rail mirrors the live EA2 work-item board for this definition. Counts, statuses, and ages come straight from the runtime API." }, + { id: "t3", anchor: "inspector", title: "Typed inspector", body: "Click any step to see its typed fields, governing rules, and evidence trail. The Raw tab gives you the EA2 payload verbatim." }, + { id: "t4", anchor: "command", title: "⌘K command palette", body: `Press ⌘K to jump between scenarios, steps, or open the guided tour for ${familyId}.` }, + { id: "t5", anchor: "telemetry", title: "Throughput rollup", body: "The bottom strip rolls up running/errored cases across every scenario you have open." }, + { id: "t6", anchor: "graph", title: "Explore", body: "That's the full loop. Switch scenarios at the top, or open ⌘K to navigate freely." }, + ]; +} + +interface CandidateBucket { + key: string; + cases: WorkItem[]; + statuses: Record; + hubs: Set; +} + +const FAMILIES = [ + { id: "procurement", label: "Procurement to Pay", subtitle: "Requisition → PO → 3-way match", accent: "#3b82f6", re: /procure|purchas|pr_to_po|atlas|requisition|po\b/i }, + { id: "ar", label: "Accounts Receivable", subtitle: "Refunds, credits & collections", accent: "#10b981", re: /refund|credit|collect|receivable|invoice/i }, + { id: "hcm", label: "People Operations", subtitle: "Onboard · Offboard · Leave", accent: "#a855f7", re: /onboard|offboard|hire|hcm|employee|leave|payroll|hr\b/i }, + { id: "gl", label: "GL Close", subtitle: "Accruals, reconciliations, journals", accent: "#f59e0b", re: /close|ledger|journal|accrual|reconcil|gl\b/i }, + { id: "service", label: "Service Operations", subtitle: "Tickets, incidents, support", accent: "#ef4444", re: /ticket|incident|support|service|case\b/i }, +]; + +export async function buildLiveScenariosFromApi(signal?: AbortSignal): Promise<{ scenarios: ProcessScenario[]; workItems: WorkItem[]; distinctDefs: number }> { + const workItems = await api.workItems(signal); + + // Bucket by definition_key with meta. + const byDef = new Map(); + for (const w of workItems) { + const k = w.definition_key; + if (!k) continue; + if (!byDef.has(k)) byDef.set(k, { key: k, cases: [], statuses: {}, hubs: new Set() }); + const b = byDef.get(k)!; + b.cases.push(w); + b.statuses[w.status] = (b.statuses[w.status] || 0) + 1; + if (w.hub) b.hubs.add(w.hub); + } + + // Candidates with ≥ 2 cases OR 1 running. + const candidates = [...byDef.values()].filter((d) => d.cases.length >= 2 || (d.statuses.running ?? 0) >= 1); + candidates.sort((a, b) => b.cases.length - a.cases.length); + + // For each candidate fetch graph + a couple runtimes. + interface Enriched { bucket: CandidateBucket; graph: ProcessGraph; headlineRt: RuntimeTransaction | null; recent: RuntimeTransaction[] } + const enriched: Enriched[] = []; + for (const c of candidates.slice(0, 20)) { + if (signal?.aborted) break; + const graph = await api.graph(c.key, signal); + if (!graph?.process_definition?.config?.nodes?.length) continue; + const headlineCase = + c.cases.find((w) => w.status === "running") || + c.cases.find((w) => w.status === "waiting_for_user") || + c.cases.find((w) => w.status === "errored" || w.status === "failed") || + c.cases[0]; + const headlineRt = headlineCase?.transaction_id ? await api.transaction(headlineCase.transaction_id, signal) : null; + const recent: RuntimeTransaction[] = []; + for (const w of c.cases.slice(0, 6)) { + if (signal?.aborted) break; + if (!w.transaction_id || w.transaction_id === headlineCase?.transaction_id) continue; + const r = await api.transaction(w.transaction_id, signal); + if (r) recent.push(r); + if (recent.length >= 3) break; + } + enriched.push({ bucket: c, graph, headlineRt, recent }); + } + + // Classify into families. + const used = new Set(); + const scenarios: ProcessScenario[] = []; + for (const fam of FAMILIES) { + const pick = enriched + .filter((e) => !used.has(e.bucket.key) && fam.re.test(`${e.graph.process_definition.display_name ?? e.graph.process_definition.name} ${[...e.bucket.hubs].join(" ")}`)) + .sort((a, b) => b.bucket.cases.length - a.bucket.cases.length)[0]; + if (!pick) continue; + used.add(pick.bucket.key); + scenarios.push( + buildScenarioFromGraph( + { id: fam.id, label: fam.label, subtitle: fam.subtitle, accent: fam.accent }, + pick.bucket.key, + pick.graph, + pick.bucket.cases, + pick.headlineRt, + pick.recent, + ), + ); + } + // Top-up with remaining largest buckets if we have fewer than 4. + const leftovers = enriched.filter((e) => !used.has(e.bucket.key)).sort((a, b) => b.bucket.cases.length - a.bucket.cases.length); + while (scenarios.length < 4 && leftovers.length) { + const e = leftovers.shift()!; + scenarios.push( + buildScenarioFromGraph( + { + id: `extra-${scenarios.length}`, + label: e.graph.process_definition.display_name || e.graph.process_definition.name, + subtitle: `${e.bucket.cases.length} live cases`, + accent: "#64748b", + }, + e.bucket.key, + e.graph, + e.bucket.cases, + e.headlineRt, + e.recent, + ), + ); + used.add(e.bucket.key); + } + return { scenarios, workItems, distinctDefs: byDef.size }; +} diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..bef5202 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/src/scenarios.json b/src/scenarios.json new file mode 100644 index 0000000..f96eabb --- /dev/null +++ b/src/scenarios.json @@ -0,0 +1,8138 @@ +{ + "fetchedFrom": "https://demo.flow-master.ai", + "fetchedAt": "2026-06-13T19:26:33.205Z", + "totals": { + "workItems": 80, + "distinctDefs": 37, + "scenarios": 3 + }, + "board": [ + { + "transaction_id": "8926f920179a49d6ad313995654db4a2", + "case_key": "8926f920179a49d6ad313995654db4a2", + "short_id": "8926f920", + "business_subject": "VERIFY-FIX-0613", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-13T17:39:47.378016+00:00", + "updated_at": "2026-06-13T17:39:47.555179+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": "223297ea028b4344bec72dbfa01dd76c", + "active_step": null, + "active_step_display_name": "Reference Review", + "next_action": "At step: Reference Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "7a9cd1d186b940d194a0640ce49dd918", + "case_key": "7a9cd1d186b940d194a0640ce49dd918", + "short_id": "7a9cd1d1", + "business_subject": "25f89310942744c98987aa7a9759af5c #7a9cd1d1", + "display_name": "25f89310942744c98987aa7a9759af5c", + "definition_name": "25f89310942744c98987aa7a9759af5c", + "definition_key": "25f89310942744c98987aa7a9759af5c", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-13T17:36:19.806293+00:00", + "updated_at": "2026-06-13T17:37:19.594177+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "d976998547804d33b4f99bb240f94a82", + "case_key": "d976998547804d33b4f99bb240f94a82", + "short_id": "d9769985", + "business_subject": "SHOW-2026-0613", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-13T17:26:36.391132+00:00", + "updated_at": "2026-06-13T17:26:36.535412+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": "223297ea028b4344bec72dbfa01dd76c", + "active_step": null, + "active_step_display_name": "Reference Review", + "next_action": "At step: Reference Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "43dee7ef94c54680bb52c934717eb713", + "case_key": "43dee7ef94c54680bb52c934717eb713", + "short_id": "43dee7ef", + "business_subject": "VERIFY-2026-0613", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-13T17:24:38.826635+00:00", + "updated_at": "2026-06-13T17:24:39.037951+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": "223297ea028b4344bec72dbfa01dd76c", + "active_step": null, + "active_step_display_name": "Reference Review", + "next_action": "At step: Reference Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "384fa003719d4675bc2fa2876c80f759", + "case_key": "384fa003719d4675bc2fa2876c80f759", + "short_id": "384fa003", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613 #384fa003", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "definition_name": "atlas-f1-fresh-20260610090831-2613", + "definition_key": "ece34cd58fab4086a47cce25fd4d63b8", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-13T15:40:22.890538+00:00", + "updated_at": "2026-06-13T15:40:23.004508+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "1909385065124b82b27a5f1f361db263", + "case_key": "1909385065124b82b27a5f1f361db263", + "short_id": "19093850", + "business_subject": "Vendor Invoice Approval v2 #19093850", + "display_name": "Vendor Invoice Approval v2", + "definition_name": "vendor_invoice_approval_process_studio_v10_mqb61if5_ed1389df", + "definition_key": "6063af7d7a2b48388bd7cfa91c717538", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-13T14:42:15.339048+00:00", + "updated_at": "2026-06-13T14:42:15.618655+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": "6063af7d7a2b48388bd7cfa91c717538_sidekick_mqb61if5_ed1389df_intake", + "active_step": null, + "active_step_display_name": "Intake", + "next_action": "At step: Intake", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "4e9a2afb0d9a47db992c3e23f1a357dd", + "case_key": "4e9a2afb0d9a47db992c3e23f1a357dd", + "short_id": "4e9a2afb", + "business_subject": "PO-FINAL-2026-0613", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T17:35:10.955372+00:00", + "updated_at": "2026-06-12T17:35:11.080494+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "223297ea028b4344bec72dbfa01dd76c", + "active_step": null, + "active_step_display_name": "Reference Review", + "next_action": "At step: Reference Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "4bbe10a44c684fe0856534c1dc7eab2e", + "case_key": "4bbe10a44c684fe0856534c1dc7eab2e", + "short_id": "4bbe10a4", + "business_subject": "PO-GUARD-2026-0613", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T17:29:47.386421+00:00", + "updated_at": "2026-06-12T17:32:07.891160+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "f3773a8bb2dd404fbcaeab976c6b5042", + "case_key": "f3773a8bb2dd404fbcaeab976c6b5042", + "short_id": "f3773a8b", + "business_subject": "PO-ADV-2026-0613", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T17:17:54.868349+00:00", + "updated_at": "2026-06-12T17:18:02.690995+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "91f14246ad2b4a059657167bdd9c4017", + "case_key": "91f14246ad2b4a059657167bdd9c4017", + "short_id": "91f14246", + "business_subject": "PO-DEMO-2026-0613-B", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T16:54:13.019702+00:00", + "updated_at": "2026-06-12T16:54:19.827044+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "8b1d0eb85da245b38ba9beb0747b1694", + "case_key": "8b1d0eb85da245b38ba9beb0747b1694", + "short_id": "8b1d0eb8", + "business_subject": "EA2 Runtime Reference #8b1d0eb8", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T16:51:41.878268+00:00", + "updated_at": "2026-06-12T16:51:42.162677+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "223297ea028b4344bec72dbfa01dd76c", + "active_step": null, + "active_step_display_name": "Reference Review", + "next_action": "At step: Reference Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "fd3da39a1acc4d66b63a7570fd469e8c", + "case_key": "fd3da39a1acc4d66b63a7570fd469e8c", + "short_id": "fd3da39a", + "business_subject": "72bda966d3bb4342b92c5a4478a7cf4e #fd3da39a", + "display_name": "72bda966d3bb4342b92c5a4478a7cf4e", + "definition_name": "72bda966d3bb4342b92c5a4478a7cf4e", + "definition_key": "72bda966d3bb4342b92c5a4478a7cf4e", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T14:53:26.935052+00:00", + "updated_at": "2026-06-12T14:53:27.052799+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "72bda966d3bb4342b92c5a4478a7cf4e_sidekick_mqb1ph31_3d4a6d3f_intake", + "active_step": null, + "active_step_display_name": "Intake", + "next_action": "At step: Intake", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "34d954b74f1b4f088a1b55d4e178ad1d", + "case_key": "34d954b74f1b4f088a1b55d4e178ad1d", + "short_id": "34d954b7", + "business_subject": "COWORK-FM-E2E-20260612", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T14:35:01.350827+00:00", + "updated_at": "2026-06-12T14:35:29.679180+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "383a350a18384193a211a5ea6f3c9b5d", + "case_key": "383a350a18384193a211a5ea6f3c9b5d", + "short_id": "383a350a", + "business_subject": "PR-SAP-ANGOLA-E2E-20260612143250", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T14:32:54.224019+00:00", + "updated_at": "2026-06-12T14:32:54.968979+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "d94278eebe7640269b8b3a4cfb8c684e", + "case_key": "d94278eebe7640269b8b3a4cfb8c684e", + "short_id": "d94278ee", + "business_subject": "PR-SAP-ANGOLA-E2E-20260612143118", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T14:31:21.214437+00:00", + "updated_at": "2026-06-12T14:31:22.123975+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "df9812fa010c42c4aed16d67acf5da19", + "case_key": "df9812fa010c42c4aed16d67acf5da19", + "short_id": "df9812fa", + "business_subject": "PR-SAP-ANGOLA-E2E-20260612143046", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T14:30:49.905685+00:00", + "updated_at": "2026-06-12T14:30:50.979373+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "89038b0e227a4a7b826ed605e3403480", + "case_key": "89038b0e227a4a7b826ed605e3403480", + "short_id": "89038b0e", + "business_subject": "adb1221961c64259bd59373d61fd9f97 #89038b0e", + "display_name": "adb1221961c64259bd59373d61fd9f97", + "definition_name": "adb1221961c64259bd59373d61fd9f97", + "definition_key": "adb1221961c64259bd59373d61fd9f97", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T13:09:18.541247+00:00", + "updated_at": "2026-06-12T13:09:31.670439+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "6524e3bbcc8645adad71014550dad8f7", + "case_key": "6524e3bbcc8645adad71014550dad8f7", + "short_id": "6524e3bb", + "business_subject": "PR-SAP-ANGOLA-E2E-20260612105554", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T10:55:57.973723+00:00", + "updated_at": "2026-06-12T10:55:58.837244+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "7cbba1d9e26c47d2989622d8d193478f", + "case_key": "7cbba1d9e26c47d2989622d8d193478f", + "short_id": "7cbba1d9", + "business_subject": "8df61a3abce04c29be918301248a56a6 #7cbba1d9", + "display_name": "8df61a3abce04c29be918301248a56a6", + "definition_name": "8df61a3abce04c29be918301248a56a6", + "definition_key": "8df61a3abce04c29be918301248a56a6", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T10:46:37.168848+00:00", + "updated_at": "2026-06-12T10:48:19.514765+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "884ee7e9792a458495cf2c0e4c698951", + "case_key": "884ee7e9792a458495cf2c0e4c698951", + "short_id": "884ee7e9", + "business_subject": "PR-SAP-ANGOLA-E2E-20260612104551", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T10:45:54.450224+00:00", + "updated_at": "2026-06-12T10:45:55.192489+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "08a23848d28c4fdc850b678a34e95778", + "case_key": "08a23848d28c4fdc850b678a34e95778", + "short_id": "08a23848", + "business_subject": "PR-SAP-ANGOLA-E2E-20260612104418", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-12T10:44:21.521427+00:00", + "updated_at": "2026-06-12T10:44:22.546015+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "ba6b061a6a3847749ad1e185fb771a2f", + "case_key": "ba6b061a6a3847749ad1e185fb771a2f", + "short_id": "ba6b061a", + "business_subject": "d403d4d7a760458793d287fc908f3f59 #ba6b061a", + "display_name": "d403d4d7a760458793d287fc908f3f59", + "definition_name": "d403d4d7a760458793d287fc908f3f59", + "definition_key": "d403d4d7a760458793d287fc908f3f59", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:57:44.608821+00:00", + "updated_at": "2026-06-12T06:57:45.277003+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "efa4c00eb7d64e359009bfb449e7fe4c", + "case_key": "efa4c00eb7d64e359009bfb449e7fe4c", + "short_id": "efa4c00e", + "business_subject": "4d79e8f644ba48d2bdde235a0ada0335 #efa4c00e", + "display_name": "4d79e8f644ba48d2bdde235a0ada0335", + "definition_name": "4d79e8f644ba48d2bdde235a0ada0335", + "definition_key": "4d79e8f644ba48d2bdde235a0ada0335", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:54:40.834844+00:00", + "updated_at": "2026-06-12T06:54:41.608911+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "c04f35ee14b341b3ac54b7eea6426823", + "case_key": "c04f35ee14b341b3ac54b7eea6426823", + "short_id": "c04f35ee", + "business_subject": "b3dae5a9099d4fda83ac2aa3d2b02840 #c04f35ee", + "display_name": "b3dae5a9099d4fda83ac2aa3d2b02840", + "definition_name": "b3dae5a9099d4fda83ac2aa3d2b02840", + "definition_key": "b3dae5a9099d4fda83ac2aa3d2b02840", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:51:27.863105+00:00", + "updated_at": "2026-06-12T06:51:28.682201+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "ce6cef9161d24c76aab7f9133073b156", + "case_key": "ce6cef9161d24c76aab7f9133073b156", + "short_id": "ce6cef91", + "business_subject": "7847162ea70f4799a80b3a50d70e21ab #ce6cef91", + "display_name": "7847162ea70f4799a80b3a50d70e21ab", + "definition_name": "7847162ea70f4799a80b3a50d70e21ab", + "definition_key": "7847162ea70f4799a80b3a50d70e21ab", + "hub": null, + "status": "completed", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:48:15.964429+00:00", + "updated_at": "2026-06-12T06:48:16.842062+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "eac8401e08d3475d955ee8c3bc1b3bd9", + "case_key": "eac8401e08d3475d955ee8c3bc1b3bd9", + "short_id": "eac8401e", + "business_subject": "08c97cf1b1444bf7ad18aee2a8d463be #eac8401e", + "display_name": "08c97cf1b1444bf7ad18aee2a8d463be", + "definition_name": "08c97cf1b1444bf7ad18aee2a8d463be", + "definition_key": "08c97cf1b1444bf7ad18aee2a8d463be", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:44:04.356067+00:00", + "updated_at": "2026-06-12T06:44:04.469559+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "08c97cf1b1444bf7ad18aee2a8d463be_sidekick_mqak922q_a070af99_intake_gate", + "active_step": null, + "active_step_display_name": "Intake Gate", + "next_action": "At step: Intake Gate", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "45dcef3c6832489d98ca5fb542512dd6", + "case_key": "45dcef3c6832489d98ca5fb542512dd6", + "short_id": "45dcef3c", + "business_subject": "a2b61518b873493b8fa36c27f9f44272 #45dcef3c", + "display_name": "a2b61518b873493b8fa36c27f9f44272", + "definition_name": "a2b61518b873493b8fa36c27f9f44272", + "definition_key": "a2b61518b873493b8fa36c27f9f44272", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:39:27.197645+00:00", + "updated_at": "2026-06-12T06:39:27.295652+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "a2b61518b873493b8fa36c27f9f44272_sidekick_mqak2v50_84ed6ae4_intake_gate", + "active_step": null, + "active_step_display_name": "Intake Gate 924819204", + "next_action": "At step: Intake Gate 924819204", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "7561705fe4774a6c840478af12fc9987", + "case_key": "7561705fe4774a6c840478af12fc9987", + "short_id": "7561705f", + "business_subject": "75baa6d3512e4be7be6374499cdcf6ee #7561705f", + "display_name": "75baa6d3512e4be7be6374499cdcf6ee", + "definition_name": "75baa6d3512e4be7be6374499cdcf6ee", + "definition_key": "75baa6d3512e4be7be6374499cdcf6ee", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:39:17.380799+00:00", + "updated_at": "2026-06-12T06:39:17.505514+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "75baa6d3512e4be7be6374499cdcf6ee_node_mqak35ad_7aedb035_75baa6d3512e4be7", + "active_step": null, + "active_step_display_name": "Archive Complete 924819204", + "next_action": "At step: Archive Complete 924819204", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "388172610b5742c18a254b9bdc10955d", + "case_key": "388172610b5742c18a254b9bdc10955d", + "short_id": "38817261", + "business_subject": "49847f146ed045e2957b1796e41e3fbb #38817261", + "display_name": "49847f146ed045e2957b1796e41e3fbb", + "definition_name": "49847f146ed045e2957b1796e41e3fbb", + "definition_key": "49847f146ed045e2957b1796e41e3fbb", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:31:58.710504+00:00", + "updated_at": "2026-06-12T06:31:58.857334+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "49847f146ed045e2957b1796e41e3fbb_node_mqajtnnb_2b4717ec_final_uat_archiv", + "active_step": null, + "active_step_display_name": "final_uat_archive_923644457_form", + "next_action": "At step: final_uat_archive_923644457_form", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "981d63e4ba014855aa464a15b70dfe14", + "case_key": "981d63e4ba014855aa464a15b70dfe14", + "short_id": "981d63e4", + "business_subject": "fcda8fca25444ee88a95641d3ef8e6fe #981d63e4", + "display_name": "fcda8fca25444ee88a95641d3ef8e6fe", + "definition_name": "fcda8fca25444ee88a95641d3ef8e6fe", + "definition_key": "fcda8fca25444ee88a95641d3ef8e6fe", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-12T06:22:50.216605+00:00", + "updated_at": "2026-06-12T06:22:50.535485+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "fcda8fca25444ee88a95641d3ef8e6fe_node_mqajhg08_29f48a65_uat_intake", + "active_step": null, + "active_step_display_name": "UAT Intake", + "next_action": "At step: UAT Intake", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "69ad28cd69904c47855af6b7827133a5", + "case_key": "69ad28cd69904c47855af6b7827133a5", + "short_id": "69ad28cd", + "business_subject": "Employee Onboarding #69ad28cd", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9lqllf_45de4c53", + "definition_key": "d6ba293866504434847654c8a03134a0", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T19:42:37.581594+00:00", + "updated_at": "2026-06-11T19:42:37.875624+00:00", + "age_days": 1, + "amount": null, + "currency": null, + "current_node": "d6ba293866504434847654c8a03134a0_node_mq9wmdsx_9be5cf9e_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "0c1bc086b6904e4e9147b59b682f9a56", + "case_key": "0c1bc086b6904e4e9147b59b682f9a56", + "short_id": "0c1bc086", + "business_subject": "Employee Onboarding #0c1bc086", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9lpdiz_a360d1be", + "definition_key": "ba935cb96eb34381b5643f018862d846", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T17:44:22.315710+00:00", + "updated_at": "2026-06-11T19:45:49.008140+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "ba935cb96eb34381b5643f018862d846_node_mq9sdik4_290ff51a_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "16712d3556f2460b89f5ddb94943b39e", + "case_key": "16712d3556f2460b89f5ddb94943b39e", + "short_id": "16712d35", + "business_subject": "Employee Onboarding #16712d35", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9mbkpy_a7e378d0", + "definition_key": "57b83d66d2994fd583cfec0de82b1b46", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T15:57:59.152072+00:00", + "updated_at": "2026-06-11T19:45:48.963192+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "57b83d66d2994fd583cfec0de82b1b46_node_mq9olu6r_8affcb98_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "38b4bd835cd142f38ca3a369c3639a30", + "case_key": "38b4bd835cd142f38ca3a369c3639a30", + "short_id": "38b4bd83", + "business_subject": "Employee Onboarding #38b4bd83", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9mgjw2_c0424656", + "definition_key": "670b98077c3b424a883125d4b9869a2d", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T15:37:32.179072+00:00", + "updated_at": "2026-06-11T19:45:48.930983+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "670b98077c3b424a883125d4b9869a2d_node_mq9nvjcf_62fe04c8_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "d256b8593ce74f289c7ba1333f7e337d", + "case_key": "d256b8593ce74f289c7ba1333f7e337d", + "short_id": "d256b859", + "business_subject": "PR-SAP-ANGOLA-E2E-20260611151919", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T15:19:23.420067+00:00", + "updated_at": "2026-06-11T15:19:25.990951+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b57ea6957e5c4382aae5c730d09eb27d", + "case_key": "b57ea6957e5c4382aae5c730d09eb27d", + "short_id": "b57ea695", + "business_subject": "PR-SAP-ANGOLA-E2E-20260611151814", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T15:18:17.989224+00:00", + "updated_at": "2026-06-11T15:18:20.640390+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "1748b69eafe64a39ab56d517f811a1dd", + "case_key": "1748b69eafe64a39ab56d517f811a1dd", + "short_id": "1748b69e", + "business_subject": "Employee Onboarding #1748b69e", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9mijky_eef2cf7f", + "definition_key": "781830a7e82941e5beab213d2726989e", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T14:59:26.308527+00:00", + "updated_at": "2026-06-11T19:45:48.903854+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "781830a7e82941e5beab213d2726989e_node_mq9mikmd_4927648a_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "74e26ea8e5964a4d961dd63c3706f0e2", + "case_key": "74e26ea8e5964a4d961dd63c3706f0e2", + "short_id": "74e26ea8", + "business_subject": "Employee Onboarding #74e26ea8", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9mgs32_8bce5317", + "definition_key": "d80a7bc5287844bcbf364f071e3b5f8c", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T14:59:03.593590+00:00", + "updated_at": "2026-06-11T19:45:48.862734+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "d80a7bc5287844bcbf364f071e3b5f8c_node_mq9mi30s_cbfcb6a6_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "1e9a429bbec840f99b31e364e9e3c2b9", + "case_key": "1e9a429bbec840f99b31e364e9e3c2b9", + "short_id": "1e9a429b", + "business_subject": "PR-ANGOLA-001 | Printer Procurement - Angola", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T14:54:48.031464+00:00", + "updated_at": "2026-06-11T14:55:03.613752+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "6be59bb639264608bccae3b55c93f9fa", + "case_key": "6be59bb639264608bccae3b55c93f9fa", + "short_id": "6be59bb6", + "business_subject": "Purchase Requisition to PO · 6be59bb6", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T14:10:28.841672+00:00", + "updated_at": "2026-06-11T14:10:28.841672+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "pr_to_po_demo_review", + "active_step": "pr_to_po_demo_review", + "active_step_display_name": "Demo Manager Review", + "next_action": "At step: Demo Manager Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "43eedf3de1bf4f59b5659ba061b3424d", + "case_key": "43eedf3de1bf4f59b5659ba061b3424d", + "short_id": "43eedf3d", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #43eedf3d", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T14:03:07.152231+00:00", + "updated_at": "2026-06-11T19:45:48.832912+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "51c8670228eb41899a20d05151d34eaa_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "3fd157c449d74211ac6ed66ec15e47eb", + "case_key": "3fd157c449d74211ac6ed66ec15e47eb", + "short_id": "3fd157c4", + "business_subject": "Employee Onboarding #3fd157c4", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9cbmqg_5eaa9059", + "definition_key": "8ddb61af0e4447b5b7c365baf1d9a2c8", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T10:24:27.975487+00:00", + "updated_at": "2026-06-11T19:45:48.752631+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "8ddb61af0e4447b5b7c365baf1d9a2c8_node_mq9coxsj_12dfb029_start", + "active_step": null, + "active_step_display_name": "Start", + "next_action": "At step: Start", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "32fcdffe3f1d4752b9b33b83336fd248", + "case_key": "32fcdffe3f1d4752b9b33b83336fd248", + "short_id": "32fcdffe", + "business_subject": "Employee Onboarding #32fcdffe", + "display_name": "Employee Onboarding", + "definition_name": "adda20c19fb640588510a84d69b02740_node_mq9c4hbb_db680332_task_mq9c5aim", + "definition_key": "adda20c19fb640588510a84d69b02740_node_mq9c4hbb_db680332_task_mq9c5aim", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T10:13:23.284997+00:00", + "updated_at": "2026-06-11T19:45:48.721775+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "adda20c19fb640588510a84d69b02740_node_mq9c4hbb_db680332_task_mq9c5aim_no", + "active_step": null, + "active_step_display_name": "New step", + "next_action": "At step: New step", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "828ec21edef344089cbb1be30623bfe6", + "case_key": "828ec21edef344089cbb1be30623bfe6", + "short_id": "828ec21e", + "business_subject": "Employee Onboarding #828ec21e", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq9c30ns_ccee0495", + "definition_key": "adda20c19fb640588510a84d69b02740", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-11T10:10:20.844295+00:00", + "updated_at": "2026-06-11T19:45:48.694685+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "adda20c19fb640588510a84d69b02740_node_mq9c4hbb_db680332_task_mq9c5aim", + "active_step": null, + "active_step_display_name": "New step", + "next_action": "At step: New step", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "4a2c20c592e64e378191d763ec1eae0a", + "case_key": "4a2c20c592e64e378191d763ec1eae0a", + "short_id": "4a2c20c5", + "business_subject": "COWORK-FORM-4-mq9c0rqu", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T10:05:39.173072+00:00", + "updated_at": "2026-06-11T10:06:05.704409+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "4a54ce758ca346a786ebdb1850877e10", + "case_key": "4a54ce758ca346a786ebdb1850877e10", + "short_id": "4a54ce75", + "business_subject": "COWORK-FORM-3-mq9by0ae", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T10:03:30.314136+00:00", + "updated_at": "2026-06-11T10:04:16.915017+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "dd8b66ea353d483f929ba15783ec92b7", + "case_key": "dd8b66ea353d483f929ba15783ec92b7", + "short_id": "dd8b66ea", + "business_subject": "COWORK-FORM-2-mq9bvvss", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T10:01:51.212980+00:00", + "updated_at": "2026-06-11T10:02:38.138809+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "76114e9bbbbc4ea28e6c2b2ede68f9eb", + "case_key": "76114e9bbbbc4ea28e6c2b2ede68f9eb", + "short_id": "76114e9b", + "business_subject": "COWORK-FORM-mq9blyjv", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T09:54:08.213270+00:00", + "updated_at": "2026-06-11T10:00:37.709263+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "622329654050422c827d351c96ebea0a", + "case_key": "622329654050422c827d351c96ebea0a", + "short_id": "62232965", + "business_subject": "Purchase Requisition to PO #62232965", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T08:02:16.338009+00:00", + "updated_at": "2026-06-11T19:45:48.650575+00:00", + "age_days": 2, + "amount": 2700, + "currency": "USD", + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b3a5bac8890945d8a4b9eae569260434", + "case_key": "b3a5bac8890945d8a4b9eae569260434", + "short_id": "b3a5bac8", + "business_subject": "REF-001", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T04:11:25.090164+00:00", + "updated_at": "2026-06-11T04:13:02.305344+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "21de2ec4d1304db891ddeefa0f404803", + "case_key": "21de2ec4d1304db891ddeefa0f404803", + "short_id": "21de2ec4", + "business_subject": "EA2 Runtime Reference #21de2ec4", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:27:10.984483+00:00", + "updated_at": "2026-06-11T19:45:48.618988+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "c0f20ec170d547948b311ffc4ba3393e", + "case_key": "c0f20ec170d547948b311ffc4ba3393e", + "short_id": "c0f20ec1", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #c0f20ec1", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "errored", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:27:09.602561+00:00", + "updated_at": "2026-06-11T19:45:48.589608+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "51c8670228eb41899a20d05151d34eaa_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "750b2ea3226d4e10be14297ec909fc81", + "case_key": "750b2ea3226d4e10be14297ec909fc81", + "short_id": "750b2ea3", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613 #750b2ea3", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "definition_name": "atlas-f1-fresh-20260610090831-2613", + "definition_key": "ece34cd58fab4086a47cce25fd4d63b8", + "hub": "procurement", + "status": "errored", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:27:08.186941+00:00", + "updated_at": "2026-06-11T19:45:48.539737+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "case_key": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "short_id": "ab8d82e5", + "business_subject": "Purchase Requisition to PO · ab8d82e5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "draft", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:25:49.888195+00:00", + "updated_at": null, + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "case_key": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "short_id": "ab8d82e5", + "business_subject": "Purchase Requisition to PO · ab8d82e5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "running", + "requester": "d0000000-0000-0000-0000-000000000099", + "requester_name": "Platform SuperAdmin", + "requester_display_name": "Platform SuperAdmin", + "created_at": "2026-06-11T03:25:49.057538", + "updated_at": "2026-06-11T03:25:50.943708", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "9656143c07414f39bcb371a3e1de4311", + "case_key": "9656143c07414f39bcb371a3e1de4311", + "short_id": "9656143c", + "business_subject": "Employee Onboarding #9656143c", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq8jis7g_16033df2", + "definition_key": "698d16520c194090a5b7ecc097345712", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-10T20:56:32.614346+00:00", + "updated_at": "2026-06-11T19:45:48.514549+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "19ef62c7faab4030b936c2078a7b65a9", + "case_key": "19ef62c7faab4030b936c2078a7b65a9", + "short_id": "19ef62c7", + "business_subject": "FM-E2E-RETRY-20260610175121", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:51:22.844202+00:00", + "updated_at": "2026-06-10T17:51:23.870527+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "5ecec9f1485b4383b99cbadf6f6a5ab5", + "case_key": "5ecec9f1485b4383b99cbadf6f6a5ab5", + "short_id": "5ecec9f1", + "business_subject": "FM-E2E-20260610175121", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:51:21.446832+00:00", + "updated_at": "2026-06-10T17:51:22.330766+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "01ffd2d844ec4146ae9dd185a6d38058", + "case_key": "01ffd2d844ec4146ae9dd185a6d38058", + "short_id": "01ffd2d8", + "business_subject": "FM-E2E-RETRY-20260610174232", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:42:34.262469+00:00", + "updated_at": "2026-06-10T17:42:35.214826+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "70063e088e934d1db9b1479029309dff", + "case_key": "70063e088e934d1db9b1479029309dff", + "short_id": "70063e08", + "business_subject": "FM-E2E-20260610174232", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:42:32.888873+00:00", + "updated_at": "2026-06-10T17:42:33.815970+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "a7f71ba99c634247b99279ff1b226be6", + "case_key": "a7f71ba99c634247b99279ff1b226be6", + "short_id": "a7f71ba9", + "business_subject": "EA2 Runtime Reference #a7f71ba9", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:41:24.372598+00:00", + "updated_at": "2026-06-11T19:45:48.485204+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "882c690ed057432594e0dd2a669f86ef", + "case_key": "882c690ed057432594e0dd2a669f86ef", + "short_id": "882c690e", + "business_subject": "FM-E2E-20260610174122", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:41:23.005230+00:00", + "updated_at": "2026-06-10T17:41:23.990868+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b91037cdca544bf78052306ea8da3ded", + "case_key": "b91037cdca544bf78052306ea8da3ded", + "short_id": "b91037cd", + "business_subject": "FM-E2E-20260610173805", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:38:05.660972+00:00", + "updated_at": "2026-06-10T17:38:06.444638+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "a49f75af91aa46da97786b5ee5aa30b8", + "case_key": "a49f75af91aa46da97786b5ee5aa30b8", + "short_id": "a49f75af", + "business_subject": "FM-E2E-20260610172715", + "display_name": "EA2 Runtime Reference", + "definition_name": "EA2 Runtime Reference", + "definition_key": "54b7d8ceba424f4d91203cda98e40b92", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T17:27:15.802029+00:00", + "updated_at": "2026-06-10T17:27:16.821962+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": "81b9d1d99e9d42a3930d44c126ebf0b2", + "active_step": null, + "active_step_display_name": "Reference Complete", + "next_action": "At step: Reference Complete", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "d3186a18e4024543aac95b488dab0d31", + "case_key": "d3186a18e4024543aac95b488dab0d31", + "short_id": "d3186a18", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #d3186a18", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:45:51.010865+00:00", + "updated_at": "2026-06-11T19:45:48.437701+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "bbf490377a7b4a5b96d58a6209157988", + "case_key": "bbf490377a7b4a5b96d58a6209157988", + "short_id": "bbf49037", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #bbf49037", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:44:49.049854+00:00", + "updated_at": "2026-06-11T19:45:48.411092+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "51a6468172114096af5a877c06a56396", + "case_key": "51a6468172114096af5a877c06a56396", + "short_id": "51a64681", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #51a64681", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "cancelled", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:43:19.827037+00:00", + "updated_at": "2026-06-11T19:45:48.385741+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "e1864722c3234958963bd2e97ef868c5", + "case_key": "e1864722c3234958963bd2e97ef868c5", + "short_id": "e1864722", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #e1864722", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "errored", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:43:11.218770+00:00", + "updated_at": "2026-06-11T19:45:48.339863+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": "51c8670228eb41899a20d05151d34eaa_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "28c2e894a09342f9806c4f7d64e17d06", + "case_key": "28c2e894a09342f9806c4f7d64e17d06", + "short_id": "28c2e894", + "business_subject": "Employee Onboarding #28c2e894", + "display_name": "Employee Onboarding", + "definition_name": "untitled_wizard_process_studio_v10_mq83va9o_c65c96d5", + "definition_key": "2e34b22ef8364383a64177fb5924b48b", + "hub": null, + "status": "running", + "requester": "a339524d-868e-4835-92de-2c26b9450b1d", + "requester_name": "Demo User", + "requester_display_name": "Demo User", + "created_at": "2026-06-10T13:34:58.522990+00:00", + "updated_at": "2026-06-11T19:45:48.312612+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": "2e34b22ef8364383a64177fb5924b48b_node_mq83vbo0_9920617f_task_mq83zdpe", + "active_step": null, + "active_step_display_name": "New step", + "next_action": "At step: New step", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "case_key": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "short_id": "b02ab1d5", + "business_subject": "Purchase Requisition to PO · b02ab1d5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "draft", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T12:43:25.457184+00:00", + "updated_at": null, + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "case_key": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "short_id": "b02ab1d5", + "business_subject": "Purchase Requisition to PO · b02ab1d5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "running", + "requester": "d0000000-0000-0000-0000-000000000099", + "requester_name": "Platform SuperAdmin", + "requester_display_name": "Platform SuperAdmin", + "created_at": "2026-06-10T12:43:24.498690", + "updated_at": "2026-06-10T12:43:26.257989", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "2c403c48471c4793b7c335d8acc24d1d", + "case_key": "2c403c48471c4793b7c335d8acc24d1d", + "short_id": "2c403c48", + "business_subject": "Approve Requisition #2c403c48", + "display_name": "Approve Requisition", + "definition_name": "approve_requisition", + "definition_key": "approve_requisition", + "hub": null, + "status": "cancelled", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T11:42:42.256508+00:00", + "updated_at": "2026-06-11T19:45:48.284817+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "demo_procurement_case_1001", + "case_key": "demo_procurement_case_1001", + "short_id": "demo_pro", + "business_subject": "Purchase Requisition to PO · demo_pro", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "draft", + "requester": "demo.flow-master.ai", + "requester_name": "FlowMaster Demo User", + "requester_display_name": "FlowMaster Demo User", + "created_at": "2026-06-10T07:51:37.645Z", + "updated_at": "2026-06-10T07:51:37.645Z", + "age_days": 3, + "amount": 12850, + "currency": "USD", + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "d2dfbd61140d4b3d8a527e28831a239c", + "case_key": "d2dfbd61140d4b3d8a527e28831a239c", + "short_id": "d2dfbd61", + "business_subject": "hms-scm-runnable-action-smoke-20260507-2128", + "display_name": "Hospital SCM Runnable Action Process", + "definition_name": "Hospital SCM Runnable Action Process", + "definition_key": "f0f6195f790c442ba71c2542917aa1b5", + "hub": "procurement", + "status": "running", + "requester": "codex-process-suite", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-05-07T21:29:24.132248+00:00", + "updated_at": "2026-05-07T21:29:46.038067+00:00", + "age_days": 36, + "amount": null, + "currency": null, + "current_node": "25fc59452a054689854fd7efeb58b7cf", + "active_step": null, + "active_step_display_name": "Clinical priority capture", + "next_action": "At step: Clinical priority capture", + "tenant_id": "hms_dev", + "group": "in_progress" + }, + { + "transaction_id": "1b394a7db21f4be2adf0a21762cc877c", + "case_key": "1b394a7db21f4be2adf0a21762cc877c", + "short_id": "1b394a7d", + "business_subject": "hms-scm-runnable-form-smoke-20260507-2124-retry", + "display_name": "Hospital SCM Runnable Form Process", + "definition_name": "Hospital SCM Runnable Form Process", + "definition_key": "049b61fe2b4f4f138a76cda003abd5c6", + "hub": "procurement", + "status": "running", + "requester": "codex-process-suite", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-05-07T21:26:21.047490+00:00", + "updated_at": "2026-06-01T10:49:30.069413+00:00", + "age_days": 36, + "amount": null, + "currency": null, + "current_node": "f3da1d6eefe64ac294d0aaffd55cc5d6", + "active_step": null, + "active_step_display_name": "Create requisition", + "next_action": "At step: Create requisition", + "tenant_id": "hms_dev", + "group": "in_progress" + }, + { + "transaction_id": "845d72fe26074367a51a462527f5165a", + "case_key": "845d72fe26074367a51a462527f5165a", + "short_id": "845d72fe", + "business_subject": "hms-scm-runnable-smoke-20260507-2122", + "display_name": "Hospital SCM Runnable Process", + "definition_name": "Hospital SCM Runnable Process", + "definition_key": "f7f20117e8654b328ab576dbb156d684", + "hub": "procurement", + "status": "running", + "requester": "codex-process-suite", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-05-07T21:23:15.942645+00:00", + "updated_at": "2026-06-01T10:49:27.702344+00:00", + "age_days": 36, + "amount": null, + "currency": null, + "current_node": "76bf876df83d4e51bc093983f7e23fff", + "active_step": null, + "active_step_display_name": "Create requisition", + "next_action": "At step: Create requisition", + "tenant_id": "hms_dev", + "group": "in_progress" + }, + { + "transaction_id": "af6e1db030754ac196925a4974a0d589", + "case_key": "af6e1db030754ac196925a4974a0d589", + "short_id": "af6e1db0", + "business_subject": "hms-scm-executable-smoke-20260507-2120", + "display_name": "Hospital SCM Executable Process", + "definition_name": "Hospital SCM Executable Process", + "definition_key": "0e1012836195400d94d3cd8c0e0b6f35", + "hub": "procurement", + "status": "running", + "requester": "codex-process-suite", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-05-07T21:21:02.928530+00:00", + "updated_at": "2026-06-01T10:49:26.887258+00:00", + "age_days": 36, + "amount": null, + "currency": null, + "current_node": "5a3d12ed5f4e4ce4a93bec109d2de034", + "active_step": null, + "active_step_display_name": "Approve clinical release, retirement or disposal", + "next_action": "At step: Approve clinical release, retirement or disposal", + "tenant_id": "hms_dev", + "group": "in_progress" + }, + { + "transaction_id": "a55340284bee49548cc72b9d799d1692", + "case_key": "a55340284bee49548cc72b9d799d1692", + "short_id": "a5534028", + "business_subject": "hms-scm-runtime-smoke-20260507-2118", + "display_name": "Hospital SCM Runtime Process Library", + "definition_name": "Hospital SCM Runtime Process Library", + "definition_key": "d3588659d7b643739428be30ecbe373c", + "hub": "procurement", + "status": "running", + "requester": "codex-process-suite", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-05-07T21:19:01.241558+00:00", + "updated_at": "2026-06-01T10:47:59.174531+00:00", + "age_days": 36, + "amount": null, + "currency": null, + "current_node": "d1267b5035e94ca89885a6a07ccf6bb5", + "active_step": null, + "active_step_display_name": "Retirement & Disposal Subprocess: impairment assessment -> retirement approval -> disposal method selection -> final accounting adjustment + audit evidence package.", + "next_action": "At step: Retirement & Disposal Subprocess: impairment assessment -> retirement approval -> disposal method selection -> final accounting adjustment + audit evidence package.", + "tenant_id": "hms_dev", + "group": "in_progress" + }, + { + "transaction_id": "ecc9dd90af9f4062ba1ec282a419fe42", + "case_key": "ecc9dd90af9f4062ba1ec282a419fe42", + "short_id": "ecc9dd90", + "business_subject": "hms-scm-import-smoke-20260507-2109", + "display_name": "Hospital SCM Process Library", + "definition_name": "Hospital SCM Process Library", + "definition_key": "e8df4808601d4e1a80ed38244a66652a", + "hub": "procurement", + "status": "running", + "requester": "codex-process-suite", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-05-07T21:13:20.914942+00:00", + "updated_at": "2026-06-01T10:47:57.942687+00:00", + "age_days": 36, + "amount": null, + "currency": null, + "current_node": "a4add15874e440f589929368f8d42356", + "active_step": null, + "active_step_display_name": "SCM vendor_management", + "next_action": "At step: SCM vendor_management", + "tenant_id": "hms_dev", + "group": "in_progress" + }, + { + "transaction_id": "fedd9c2dde9d4c0896d67ca1c1c5b90d", + "case_key": "fedd9c2dde9d4c0896d67ca1c1c5b90d", + "short_id": "fedd9c2d", + "business_subject": "PO Approval · fedd9c2d", + "display_name": "PO Approval", + "definition_name": "po_approval_def_9942aa", + "definition_key": "b97aa4ea308c4dc594ed23328861e9bf", + "hub": "procurement", + "status": "draft", + "requester": "system:seed", + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-04-22T20:30:44.711388+00:00", + "updated_at": "2026-04-22T20:30:44.711388+00:00", + "age_days": 51, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "hub-cnt-f56ce0", + "group": "in_progress" + } + ], + "scenarios": [ + { + "id": "procurement", + "family": { + "id": "procurement", + "label": "Procurement to Pay", + "subtitle": "Requisition → PO → 3-way match", + "accent": "#3b82f6" + }, + "def_key": "pr_to_po_def", + "def_name": "Purchase Requisition to PO", + "hubs": [ + "procurement" + ], + "statuses": { + "running": 3, + "completed": 1, + "draft": 3 + }, + "cases": [ + { + "transaction_id": "6be59bb639264608bccae3b55c93f9fa", + "case_key": "6be59bb639264608bccae3b55c93f9fa", + "short_id": "6be59bb6", + "business_subject": "Purchase Requisition to PO · 6be59bb6", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T14:10:28.841672+00:00", + "updated_at": "2026-06-11T14:10:28.841672+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "pr_to_po_demo_review", + "active_step": "pr_to_po_demo_review", + "active_step_display_name": "Demo Manager Review", + "next_action": "At step: Demo Manager Review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "622329654050422c827d351c96ebea0a", + "case_key": "622329654050422c827d351c96ebea0a", + "short_id": "62232965", + "business_subject": "Purchase Requisition to PO #62232965", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T08:02:16.338009+00:00", + "updated_at": "2026-06-11T19:45:48.650575+00:00", + "age_days": 2, + "amount": 2700, + "currency": "USD", + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "case_key": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "short_id": "ab8d82e5", + "business_subject": "Purchase Requisition to PO · ab8d82e5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "draft", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:25:49.888195+00:00", + "updated_at": null, + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "case_key": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "short_id": "ab8d82e5", + "business_subject": "Purchase Requisition to PO · ab8d82e5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "running", + "requester": "d0000000-0000-0000-0000-000000000099", + "requester_name": "Platform SuperAdmin", + "requester_display_name": "Platform SuperAdmin", + "created_at": "2026-06-11T03:25:49.057538", + "updated_at": "2026-06-11T03:25:50.943708", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "case_key": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "short_id": "b02ab1d5", + "business_subject": "Purchase Requisition to PO · b02ab1d5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "draft", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T12:43:25.457184+00:00", + "updated_at": null, + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "case_key": "b02ab1d5-e7ed-4a55-831c-6eaf879635b9", + "short_id": "b02ab1d5", + "business_subject": "Purchase Requisition to PO · b02ab1d5", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "running", + "requester": "d0000000-0000-0000-0000-000000000099", + "requester_name": "Platform SuperAdmin", + "requester_display_name": "Platform SuperAdmin", + "created_at": "2026-06-10T12:43:24.498690", + "updated_at": "2026-06-10T12:43:26.257989", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "demo_procurement_case_1001", + "case_key": "demo_procurement_case_1001", + "short_id": "demo_pro", + "business_subject": "Purchase Requisition to PO · demo_pro", + "display_name": "Purchase Requisition to PO", + "definition_name": "pr_to_po_def", + "definition_key": "pr_to_po_def", + "hub": "procurement", + "status": "draft", + "requester": "demo.flow-master.ai", + "requester_name": "FlowMaster Demo User", + "requester_display_name": "FlowMaster Demo User", + "created_at": "2026-06-10T07:51:37.645Z", + "updated_at": "2026-06-10T07:51:37.645Z", + "age_days": 3, + "amount": 12850, + "currency": "USD", + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "Submit for review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + } + ], + "graph": { + "process_definition": { + "_id": "flow/pr_to_po_def", + "_key": "pr_to_po_def", + "config": { + "edges": [ + { + "id": "start_to_review", + "source": "start", + "target": "manager_review" + }, + { + "id": "review_to_approved", + "source": "manager_review", + "target": "approved", + "outcome": "complete" + } + ], + "executable": true, + "is_executable": true, + "nodes": [ + { + "id": "start", + "type": "start", + "label": "Request submitted" + }, + { + "id": "manager_review", + "type": "human_task", + "label": "Manager review", + "form_ref": "purchase_requisition_def", + "actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "complete" + } + ] + }, + { + "id": "approved", + "type": "end", + "label": "Approved" + } + ], + "org_id": "a0000000-0000-0000-0000-000000000010" + }, + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Executable curated procurement process for demo.flow-master.ai reset smoke checks.", + "display_name": "Purchase Requisition to PO", + "hub": "procurement", + "kind": "definition", + "label": "Purchase Requisition to PO", + "name": "pr_to_po_def", + "source_context": "fm06-t10-demo-reset-v2", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T07:51:37.645Z", + "version": 1 + }, + "nodes": [ + { + "_id": "flow/po_change_cancel", + "_key": "po_change_cancel", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "buyer" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "buyer" + } + ], + "config": { + "action_type": "human_task", + "step": "po_change_cancel" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Manage changes, cancellations, replacement PO links, and supplier notification.", + "display_name": "Change or Cancel PO", + "kind": "definition", + "label": "Change or Cancel PO", + "name": "po_change_cancel", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number" + }, + { + "name": "change_type", + "label": "Change Type", + "type": "string", + "required": true, + "description": "Change Type" + }, + { + "name": "change_reason", + "label": "Change Reason", + "type": "textarea", + "required": true, + "description": "Change Reason" + }, + { + "name": "change_approval_status", + "label": "Change Approval Status", + "type": "string", + "required": true, + "description": "Change Approval Status" + }, + { + "name": "replacement_po_number", + "label": "Replacement PO Number", + "type": "string", + "required": false, + "description": "Replacement PO Number" + } + ], + "presentation_view_id": "po_change_cancel_view", + "rule_ref": null, + "human_role": "buyer", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/po_sent", + "_key": "po_sent", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "buyer" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "buyer" + } + ], + "config": { + "action_type": "human_task", + "step": "po_sent" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Record supplier acknowledgement and final PO sent status.", + "display_name": "PO Sent", + "kind": "definition", + "label": "PO Sent", + "name": "po_sent", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "sent_to_supplier" + }, + { + "name": "supplier_acknowledgement", + "label": "Supplier Acknowledgement", + "type": "string", + "required": true, + "description": "Supplier Acknowledgement" + }, + { + "name": "acknowledged_at", + "label": "Acknowledged At", + "type": "datetime", + "required": false, + "description": "Acknowledged At" + } + ], + "presentation_view_id": "po_sent_view", + "rule_ref": null, + "human_role": "buyer", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/dispatch_po", + "_key": "dispatch_po", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "buyer" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "buyer" + } + ], + "config": { + "action_type": "human_task", + "step": "dispatch_po" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Send PO to supplier and record dispatch evidence.", + "display_name": "Send to Supplier", + "kind": "definition", + "label": "Send to Supplier", + "name": "dispatch_po", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "dispatch_method", + "label": "Dispatch Method", + "type": "string", + "required": true, + "description": "Dispatch Method" + }, + { + "name": "supplier_contact", + "label": "Supplier Contact", + "type": "string", + "required": true, + "description": "Supplier Contact" + }, + { + "name": "supplier_sent_at", + "label": "Supplier Sent At", + "type": "datetime", + "required": true, + "description": "Supplier Sent At" + }, + { + "name": "dispatch_evidence", + "label": "Dispatch Evidence", + "type": "array", + "required": false, + "description": "Dispatch Evidence" + } + ], + "presentation_view_id": "po_dispatch_view", + "rule_ref": null, + "human_role": "buyer", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/po_ready", + "_key": "po_ready", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "procurement_user" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "procurement_user" + } + ], + "config": { + "action_type": "human_task", + "step": "po_ready" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Mark the PO ready to send after validations pass.", + "display_name": "PO Ready", + "kind": "definition", + "label": "PO Ready", + "name": "po_ready", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "ready_to_send" + }, + { + "name": "release_checklist", + "label": "Release Checklist", + "type": "array", + "required": true, + "description": "Release Checklist" + }, + { + "name": "ready_approved_by", + "label": "Ready Approved By", + "type": "string", + "required": true, + "description": "Ready Approved By" + } + ], + "presentation_view_id": "po_ready_view", + "rule_ref": null, + "human_role": "procurement_user", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/legal_finance_review", + "_key": "legal_finance_review", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "finance_controller" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "finance_controller" + } + ], + "config": { + "action_type": "human_task", + "step": "legal_finance_review" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Review legal, finance, compliance, or threshold exceptions before release.", + "display_name": "Review Exceptions", + "kind": "definition", + "label": "Review Exceptions", + "name": "legal_finance_review", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "exception_type", + "label": "Exception Type", + "type": "string", + "required": true, + "description": "Exception Type" + }, + { + "name": "exception_owner", + "label": "Exception Owner", + "type": "string", + "required": true, + "description": "Exception Owner" + }, + { + "name": "exception_decision", + "label": "Exception Decision", + "type": "string", + "required": true, + "description": "Exception Decision" + }, + { + "name": "approval_comments", + "label": "Approval Comments", + "type": "textarea", + "required": false, + "description": "Approval Comments" + } + ], + "presentation_view_id": "exception_review_view", + "rule_ref": null, + "human_role": "finance_controller", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/prepare_po", + "_key": "prepare_po", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "buyer" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "buyer" + } + ], + "config": { + "action_type": "human_task", + "step": "prepare_po" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Convert approved requisition into a PO draft with commercial terms and delivery instructions.", + "display_name": "Prepare Purchase Order", + "kind": "definition", + "label": "Prepare Purchase Order", + "name": "prepare_po", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "ready_to_send" + }, + { + "name": "dispatch_method", + "label": "Dispatch Method", + "type": "string", + "required": true, + "description": "Dispatch Method" + }, + { + "name": "supplier_sent_at", + "label": "Supplier Sent At", + "type": "datetime", + "required": false, + "description": "Supplier Sent At" + } + ], + "presentation_view_id": "po_preparation_view", + "rule_ref": null, + "human_role": "buyer", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/source_or_confirm", + "_key": "source_or_confirm", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "buyer" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "buyer" + } + ], + "config": { + "action_type": "human_task", + "step": "source_or_confirm" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Confirm catalog, quote, contract, or spot-buy route and selected supplier.", + "display_name": "Confirm Source", + "kind": "definition", + "label": "Confirm Source", + "name": "source_or_confirm", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "requester_department", + "label": "Requester Department", + "type": "string", + "required": true, + "description": "Requester Department" + }, + { + "name": "business_unit", + "label": "Business Unit", + "type": "string", + "required": true, + "description": "Business Unit" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "required_date", + "label": "Required Date", + "type": "date", + "required": true, + "description": "Required Date" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "tax_total", + "label": "Tax Total", + "type": "number", + "required": false, + "description": "Tax Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "justification", + "label": "Business Justification", + "type": "textarea", + "required": true, + "description": "Business Justification" + }, + { + "name": "attachments", + "label": "Attachments", + "type": "array", + "required": false, + "description": "Attachments" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": true, + "description": "Supplier Reference" + }, + { + "name": "supplier_status", + "label": "Supplier Status", + "type": "string", + "required": true, + "description": "Supplier Status" + }, + { + "name": "payment_terms", + "label": "Payment Terms", + "type": "string", + "required": true, + "description": "Payment Terms" + }, + { + "name": "incoterms", + "label": "Incoterms", + "type": "string", + "required": false, + "description": "Incoterms" + }, + { + "name": "compliance_status", + "label": "Compliance Status", + "type": "string", + "required": true, + "description": "Compliance Status" + } + ], + "presentation_view_id": "sourcing_confirmation_view", + "rule_ref": null, + "human_role": "buyer", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/supplier_validation", + "_key": "supplier_validation", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "procurement_user" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "procurement_user" + } + ], + "config": { + "action_type": "human_task", + "step": "supplier_validation" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Confirm supplier master, payment terms, compliance status, and onboarding gaps.", + "display_name": "Validate Supplier", + "kind": "definition", + "label": "Validate Supplier", + "name": "supplier_validation", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": true, + "description": "Supplier Reference" + }, + { + "name": "supplier_status", + "label": "Supplier Status", + "type": "string", + "required": true, + "description": "Supplier Status" + }, + { + "name": "payment_terms", + "label": "Payment Terms", + "type": "string", + "required": true, + "description": "Payment Terms" + }, + { + "name": "incoterms", + "label": "Incoterms", + "type": "string", + "required": false, + "description": "Incoterms" + }, + { + "name": "compliance_status", + "label": "Compliance Status", + "type": "string", + "required": true, + "description": "Compliance Status" + } + ], + "presentation_view_id": "supplier_validation_view", + "rule_ref": null, + "human_role": "procurement_user", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/approve_requisition", + "_key": "approve_requisition", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "line_manager" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "line_manager" + } + ], + "config": { + "action_type": "human_task", + "step": "approve_requisition" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Manager confirms business need, timing, quantity, and spend authority.", + "display_name": "Approve Requisition", + "kind": "definition", + "label": "Approve Requisition", + "name": "approve_requisition", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "manager_decision", + "label": "Manager Decision", + "type": "string", + "required": true, + "description": "Manager Decision" + }, + { + "name": "approval_comments", + "label": "Approval Comments", + "type": "textarea", + "required": false, + "description": "Approval Comments" + } + ], + "presentation_view_id": "requisition_approval_view", + "rule_ref": null, + "human_role": "line_manager", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/budget_check", + "_key": "budget_check", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "finance_controller" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "finance_controller" + } + ], + "config": { + "action_type": "human_task", + "step": "budget_check" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Validate cost center, GL/project coding, budget availability, tax treatment, and approval route.", + "display_name": "Check Budget", + "kind": "definition", + "label": "Check Budget", + "name": "budget_check", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "budget_available", + "label": "Budget Available", + "type": "boolean", + "required": true, + "description": "Budget Available" + }, + { + "name": "approval_limit", + "label": "Approval Limit", + "type": "number", + "required": true, + "description": "Approval Limit" + }, + { + "name": "budget_check_result", + "label": "Budget Check Result", + "type": "string", + "required": true, + "description": "Budget Check Result" + }, + { + "name": "approval_route", + "label": "Approval Route", + "type": "string", + "required": true, + "description": "Approval Route" + } + ], + "presentation_view_id": "budget_check_view", + "rule_ref": null, + "human_role": "finance_controller", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/pr_intake", + "_key": "pr_intake", + "actions": [ + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "requester" + }, + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "requester" + } + ], + "config": { + "action_type": "human_task", + "step": "pr_intake" + }, + "created_at": "2026-06-10T11:22:41.393286+00:00", + "description": "Requester captures need, supplier, line items, accounting, required date, justification, and attachments.", + "display_name": "Create Requisition", + "kind": "definition", + "label": "Create Requisition", + "name": "pr_intake", + "position": null, + "source_context": null, + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.193237+00:00", + "version": null, + "form_fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "requester_department", + "label": "Requester Department", + "type": "string", + "required": true, + "description": "Requester Department" + }, + { + "name": "business_unit", + "label": "Business Unit", + "type": "string", + "required": true, + "description": "Business Unit" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "required_date", + "label": "Required Date", + "type": "date", + "required": true, + "description": "Required Date" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "tax_total", + "label": "Tax Total", + "type": "number", + "required": false, + "description": "Tax Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "justification", + "label": "Business Justification", + "type": "textarea", + "required": true, + "description": "Business Justification" + }, + { + "name": "attachments", + "label": "Attachments", + "type": "array", + "required": false, + "description": "Attachments" + } + ], + "presentation_view_id": "pr_intake_view", + "rule_ref": null, + "human_role": "requester", + "agent_capability": null, + "dispatch_kind": "human" + }, + { + "_id": "flow/pr_to_po_demo_review", + "_key": "pr_to_po_demo_review", + "config": { + "is_entry_node": true, + "runtime_entry": true, + "actions": [ + { + "id": "save_draft", + "label": "Save Draft", + "display_label": "Save Draft", + "kind": "save_draft", + "for_role": "requester", + "requires_human_confirmation": false + }, + { + "id": "submit", + "label": "Submit", + "display_label": "Submit", + "kind": "submit", + "for_role": "requester" + } + ] + }, + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Human review step seeded for the live demo smoke runtime action contract.", + "display_name": "Demo Manager Review", + "kind": "definition", + "label": "Demo Manager Review", + "name": "pr_to_po_demo_review", + "source_context": "fm06-t10-demo-reset-v2", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T07:51:37.645Z", + "version": 1, + "form_fields": [ + { + "name": "request_number", + "type": "string", + "required": true, + "label": "Request #", + "is_subject": true + }, + { + "name": "supplier", + "type": "string", + "required": true, + "label": "Supplier" + }, + { + "name": "total_amount", + "type": "number", + "required": true, + "label": "Amount" + }, + { + "name": "currency", + "type": "string", + "required": true, + "label": "Currency" + }, + { + "name": "status", + "type": "string", + "required": true, + "label": "Status" + } + ], + "presentation_view_id": "pr_to_po_demo_review_view", + "rule_ref": null, + "actions": [], + "human_role": "requester", + "agent_capability": null, + "dispatch_kind": "human" + } + ], + "edges": [ + { + "_from": "flow/pr_to_po_def", + "_to": "flow/approve_requisition", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "approve_requisition", + "to_id": "flow/approve_requisition", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/budget_check", + "_to": "flow/approve_requisition", + "from": "budget_check", + "from_id": "flow/budget_check", + "to": "approve_requisition", + "to_id": "flow/approve_requisition", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/budget_check", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "budget_check", + "to_id": "flow/budget_check", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/pr_intake", + "_to": "flow/budget_check", + "from": "pr_intake", + "from_id": "flow/pr_intake", + "to": "budget_check", + "to_id": "flow/budget_check", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/dispatch_po", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "dispatch_po", + "to_id": "flow/dispatch_po", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/po_ready", + "_to": "flow/dispatch_po", + "from": "po_ready", + "from_id": "flow/po_ready", + "to": "dispatch_po", + "to_id": "flow/dispatch_po", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/legal_finance_review", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "legal_finance_review", + "to_id": "flow/legal_finance_review", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/prepare_po", + "_to": "flow/legal_finance_review", + "from": "prepare_po", + "from_id": "flow/prepare_po", + "to": "legal_finance_review", + "to_id": "flow/legal_finance_review", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/po_change_cancel", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_change_cancel", + "to_id": "flow/po_change_cancel", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/po_ready", + "_to": "flow/po_change_cancel", + "from": "po_ready", + "from_id": "flow/po_ready", + "to": "po_change_cancel", + "to_id": "flow/po_change_cancel", + "collection": "defines", + "role": "next", + "label": "change_or_cancel" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/po_ready", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_ready", + "to_id": "flow/po_ready", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/legal_finance_review", + "_to": "flow/po_ready", + "from": "legal_finance_review", + "from_id": "flow/legal_finance_review", + "to": "po_ready", + "to_id": "flow/po_ready", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/po_sent", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_sent", + "to_id": "flow/po_sent", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/dispatch_po", + "_to": "flow/po_sent", + "from": "dispatch_po", + "from_id": "flow/dispatch_po", + "to": "po_sent", + "to_id": "flow/po_sent", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/pr_intake", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "pr_intake", + "to_id": "flow/pr_intake", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/pr_to_po_demo_review", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "pr_to_po_demo_review", + "to_id": "flow/pr_to_po_demo_review", + "collection": "defines", + "role": "child", + "label": "Demo entry" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/prepare_po", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "prepare_po", + "to_id": "flow/prepare_po", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/source_or_confirm", + "_to": "flow/prepare_po", + "from": "source_or_confirm", + "from_id": "flow/source_or_confirm", + "to": "prepare_po", + "to_id": "flow/prepare_po", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/source_or_confirm", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "source_or_confirm", + "to_id": "flow/source_or_confirm", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/supplier_validation", + "_to": "flow/source_or_confirm", + "from": "supplier_validation", + "from_id": "flow/supplier_validation", + "to": "source_or_confirm", + "to_id": "flow/source_or_confirm", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "flow/supplier_validation", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "supplier_validation", + "to_id": "flow/supplier_validation", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/approve_requisition", + "_to": "flow/supplier_validation", + "from": "approve_requisition", + "from_id": "flow/approve_requisition", + "to": "supplier_validation", + "to_id": "flow/supplier_validation", + "collection": "defines", + "role": "next", + "label": null + }, + { + "_from": "flow/approve_requisition", + "_to": "flow/approve_requisition", + "from": "approve_requisition", + "from_id": "flow/approve_requisition", + "to": "approve_requisition", + "to_id": "flow/approve_requisition", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/approve_requisition", + "_to": "data/requisition_approval_def", + "from": "approve_requisition", + "from_id": "flow/approve_requisition", + "to": "requisition_approval_def", + "to_id": "data/requisition_approval_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/approve_requisition", + "_to": "view/requisition_approval_view", + "from": "approve_requisition", + "from_id": "flow/approve_requisition", + "to": "requisition_approval_view", + "to_id": "view/requisition_approval_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/budget_check", + "_to": "flow/budget_check", + "from": "budget_check", + "from_id": "flow/budget_check", + "to": "budget_check", + "to_id": "flow/budget_check", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/budget_check", + "_to": "data/budget_check_def", + "from": "budget_check", + "from_id": "flow/budget_check", + "to": "budget_check_def", + "to_id": "data/budget_check_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/budget_check", + "_to": "view/budget_check_view", + "from": "budget_check", + "from_id": "flow/budget_check", + "to": "budget_check_view", + "to_id": "view/budget_check_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/dispatch_po", + "_to": "flow/dispatch_po", + "from": "dispatch_po", + "from_id": "flow/dispatch_po", + "to": "dispatch_po", + "to_id": "flow/dispatch_po", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/dispatch_po", + "_to": "data/po_dispatch_def", + "from": "dispatch_po", + "from_id": "flow/dispatch_po", + "to": "po_dispatch_def", + "to_id": "data/po_dispatch_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/dispatch_po", + "_to": "data/po_dispatch_def", + "from": "dispatch_po", + "from_id": "flow/dispatch_po", + "to": "po_dispatch_def", + "to_id": "data/po_dispatch_def", + "collection": "defines", + "role": "output", + "label": null + }, + { + "_from": "flow/dispatch_po", + "_to": "view/po_dispatch_view", + "from": "dispatch_po", + "from_id": "flow/dispatch_po", + "to": "po_dispatch_view", + "to_id": "view/po_dispatch_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/legal_finance_review", + "_to": "flow/legal_finance_review", + "from": "legal_finance_review", + "from_id": "flow/legal_finance_review", + "to": "legal_finance_review", + "to_id": "flow/legal_finance_review", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/legal_finance_review", + "_to": "data/exception_review_def", + "from": "legal_finance_review", + "from_id": "flow/legal_finance_review", + "to": "exception_review_def", + "to_id": "data/exception_review_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/legal_finance_review", + "_to": "view/exception_review_view", + "from": "legal_finance_review", + "from_id": "flow/legal_finance_review", + "to": "exception_review_view", + "to_id": "view/exception_review_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/po_change_cancel", + "_to": "flow/po_change_cancel", + "from": "po_change_cancel", + "from_id": "flow/po_change_cancel", + "to": "po_change_cancel", + "to_id": "flow/po_change_cancel", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/po_change_cancel", + "_to": "data/po_change_cancel_def", + "from": "po_change_cancel", + "from_id": "flow/po_change_cancel", + "to": "po_change_cancel_def", + "to_id": "data/po_change_cancel_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/po_change_cancel", + "_to": "view/po_change_cancel_view", + "from": "po_change_cancel", + "from_id": "flow/po_change_cancel", + "to": "po_change_cancel_view", + "to_id": "view/po_change_cancel_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/po_ready", + "_to": "flow/po_ready", + "from": "po_ready", + "from_id": "flow/po_ready", + "to": "po_ready", + "to_id": "flow/po_ready", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/po_ready", + "_to": "data/po_ready_def", + "from": "po_ready", + "from_id": "flow/po_ready", + "to": "po_ready_def", + "to_id": "data/po_ready_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/po_ready", + "_to": "data/po_ready_def", + "from": "po_ready", + "from_id": "flow/po_ready", + "to": "po_ready_def", + "to_id": "data/po_ready_def", + "collection": "defines", + "role": "output", + "label": null + }, + { + "_from": "flow/po_ready", + "_to": "view/po_ready_view", + "from": "po_ready", + "from_id": "flow/po_ready", + "to": "po_ready_view", + "to_id": "view/po_ready_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/po_sent", + "_to": "flow/po_sent", + "from": "po_sent", + "from_id": "flow/po_sent", + "to": "po_sent", + "to_id": "flow/po_sent", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/po_sent", + "_to": "data/po_sent_def", + "from": "po_sent", + "from_id": "flow/po_sent", + "to": "po_sent_def", + "to_id": "data/po_sent_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/po_sent", + "_to": "data/po_sent_def", + "from": "po_sent", + "from_id": "flow/po_sent", + "to": "po_sent_def", + "to_id": "data/po_sent_def", + "collection": "defines", + "role": "output", + "label": null + }, + { + "_from": "flow/po_sent", + "_to": "view/po_sent_view", + "from": "po_sent", + "from_id": "flow/po_sent", + "to": "po_sent_view", + "to_id": "view/po_sent_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/pr_intake", + "_to": "flow/pr_intake", + "from": "pr_intake", + "from_id": "flow/pr_intake", + "to": "pr_intake", + "to_id": "flow/pr_intake", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/pr_intake", + "_to": "data/purchase_requisition_def", + "from": "pr_intake", + "from_id": "flow/pr_intake", + "to": "purchase_requisition_def", + "to_id": "data/purchase_requisition_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/pr_intake", + "_to": "view/pr_intake_view", + "from": "pr_intake", + "from_id": "flow/pr_intake", + "to": "pr_intake_view", + "to_id": "view/pr_intake_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/budget_check_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "budget_check_def", + "to_id": "data/budget_check_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Budget Checks" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/exception_review_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "exception_review_def", + "to_id": "data/exception_review_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Exception Reviews" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/po_change_cancel_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_change_cancel_def", + "to_id": "data/po_change_cancel_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Po Change Cancels" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/po_dispatch_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_dispatch_def", + "to_id": "data/po_dispatch_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Po Dispatch" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/po_ready_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_ready_def", + "to_id": "data/po_ready_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Po Readys" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/po_sent_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "po_sent_def", + "to_id": "data/po_sent_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Po Sents" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/purchase_order_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "purchase_order_def", + "to_id": "data/purchase_order_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Purchase Orders" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/purchase_requisition_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "purchase_requisition_def", + "to_id": "data/purchase_requisition_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Purchase Requisitions" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/requisition_approval_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "requisition_approval_def", + "to_id": "data/requisition_approval_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Requisition Approvals" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/supplier_validation_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "supplier_validation_def", + "to_id": "data/supplier_validation_def", + "collection": "defines", + "role": "input", + "label": "Input entity: Supplier Validations" + }, + { + "_from": "flow/pr_to_po_def", + "_to": "data/purchase_order_def", + "from": "pr_to_po_def", + "from_id": "flow/pr_to_po_def", + "to": "purchase_order_def", + "to_id": "data/purchase_order_def", + "collection": "defines", + "role": "output", + "label": null + }, + { + "_from": "flow/pr_to_po_demo_review", + "_to": "flow/pr_to_po_demo_review", + "from": "pr_to_po_demo_review", + "from_id": "flow/pr_to_po_demo_review", + "to": "pr_to_po_demo_review", + "to_id": "flow/pr_to_po_demo_review", + "collection": "defines", + "role": "dispatch", + "label": "Human review" + }, + { + "_from": "flow/pr_to_po_demo_review", + "_to": "data/purchase_requisition_def", + "from": "pr_to_po_demo_review", + "from_id": "flow/pr_to_po_demo_review", + "to": "purchase_requisition_def", + "to_id": "data/purchase_requisition_def", + "collection": "defines", + "role": "input", + "label": "Purchase requisition input" + }, + { + "_from": "flow/pr_to_po_demo_review", + "_to": "view/pr_to_po_demo_review_view", + "from": "pr_to_po_demo_review", + "from_id": "flow/pr_to_po_demo_review", + "to": "pr_to_po_demo_review_view", + "to_id": "view/pr_to_po_demo_review_view", + "collection": "defines", + "role": "presentation", + "label": "Demo review form" + }, + { + "_from": "flow/prepare_po", + "_to": "flow/prepare_po", + "from": "prepare_po", + "from_id": "flow/prepare_po", + "to": "prepare_po", + "to_id": "flow/prepare_po", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/prepare_po", + "_to": "data/purchase_order_def", + "from": "prepare_po", + "from_id": "flow/prepare_po", + "to": "purchase_order_def", + "to_id": "data/purchase_order_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/prepare_po", + "_to": "data/purchase_order_def", + "from": "prepare_po", + "from_id": "flow/prepare_po", + "to": "purchase_order_def", + "to_id": "data/purchase_order_def", + "collection": "defines", + "role": "output", + "label": null + }, + { + "_from": "flow/prepare_po", + "_to": "view/po_preparation_view", + "from": "prepare_po", + "from_id": "flow/prepare_po", + "to": "po_preparation_view", + "to_id": "view/po_preparation_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/source_or_confirm", + "_to": "flow/source_or_confirm", + "from": "source_or_confirm", + "from_id": "flow/source_or_confirm", + "to": "source_or_confirm", + "to_id": "flow/source_or_confirm", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/source_or_confirm", + "_to": "data/supplier_validation_def", + "from": "source_or_confirm", + "from_id": "flow/source_or_confirm", + "to": "supplier_validation_def", + "to_id": "data/supplier_validation_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/source_or_confirm", + "_to": "view/sourcing_confirmation_view", + "from": "source_or_confirm", + "from_id": "flow/source_or_confirm", + "to": "sourcing_confirmation_view", + "to_id": "view/sourcing_confirmation_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "flow/supplier_validation", + "_to": "flow/supplier_validation", + "from": "supplier_validation", + "from_id": "flow/supplier_validation", + "to": "supplier_validation", + "to_id": "flow/supplier_validation", + "collection": "defines", + "role": "dispatch", + "label": null + }, + { + "_from": "flow/supplier_validation", + "_to": "data/supplier_validation_def", + "from": "supplier_validation", + "from_id": "flow/supplier_validation", + "to": "supplier_validation_def", + "to_id": "data/supplier_validation_def", + "collection": "defines", + "role": "input", + "label": null + }, + { + "_from": "flow/supplier_validation", + "_to": "view/supplier_validation_view", + "from": "supplier_validation", + "from_id": "flow/supplier_validation", + "to": "supplier_validation_view", + "to_id": "view/supplier_validation_view", + "collection": "defines", + "role": "presentation", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/budget_check_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "budget_check_def", + "to_id": "data/budget_check_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/exception_review_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "exception_review_def", + "to_id": "data/exception_review_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/po_change_cancel_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_change_cancel_def", + "to_id": "data/po_change_cancel_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/po_dispatch_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_dispatch_def", + "to_id": "data/po_dispatch_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/po_ready_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_ready_def", + "to_id": "data/po_ready_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/po_sent_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_sent_def", + "to_id": "data/po_sent_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/purchase_order_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "purchase_order_def", + "to_id": "data/purchase_order_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/purchase_requisition_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "purchase_requisition_def", + "to_id": "data/purchase_requisition_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/requisition_approval_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "requisition_approval_def", + "to_id": "data/requisition_approval_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "data/supplier_validation_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "supplier_validation_def", + "to_id": "data/supplier_validation_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/approve_requisition", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "approve_requisition", + "to_id": "flow/approve_requisition", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/budget_check", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "budget_check", + "to_id": "flow/budget_check", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/dispatch_po", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "dispatch_po", + "to_id": "flow/dispatch_po", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/legal_finance_review", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "legal_finance_review", + "to_id": "flow/legal_finance_review", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/po_change_cancel", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_change_cancel", + "to_id": "flow/po_change_cancel", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/po_ready", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_ready", + "to_id": "flow/po_ready", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/po_sent", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_sent", + "to_id": "flow/po_sent", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/pr_intake", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "pr_intake", + "to_id": "flow/pr_intake", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/pr_to_po_def", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "pr_to_po_def", + "to_id": "flow/pr_to_po_def", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/pr_to_po_demo_review", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "pr_to_po_demo_review", + "to_id": "flow/pr_to_po_demo_review", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/prepare_po", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "prepare_po", + "to_id": "flow/prepare_po", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/source_or_confirm", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "source_or_confirm", + "to_id": "flow/source_or_confirm", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "flow/supplier_validation", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "supplier_validation", + "to_id": "flow/supplier_validation", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "rule/budget_and_threshold_rule", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "budget_and_threshold_rule", + "to_id": "rule/budget_and_threshold_rule", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "rule/po_change_cancel_rule", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_change_cancel_rule", + "to_id": "rule/po_change_cancel_rule", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "rule/po_release_rule", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_release_rule", + "to_id": "rule/po_release_rule", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "rule/pr_to_po_demo_review_rule", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "pr_to_po_demo_review_rule", + "to_id": "rule/pr_to_po_demo_review_rule", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "rule/supplier_compliance_rule", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "supplier_compliance_rule", + "to_id": "rule/supplier_compliance_rule", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/budget_check_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "budget_check_view", + "to_id": "view/budget_check_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/exception_review_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "exception_review_view", + "to_id": "view/exception_review_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/po_change_cancel_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_change_cancel_view", + "to_id": "view/po_change_cancel_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/po_dispatch_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_dispatch_view", + "to_id": "view/po_dispatch_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/po_preparation_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_preparation_view", + "to_id": "view/po_preparation_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/po_ready_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_ready_view", + "to_id": "view/po_ready_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/po_sent_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "po_sent_view", + "to_id": "view/po_sent_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/pr_intake_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "pr_intake_view", + "to_id": "view/pr_intake_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/pr_to_po_demo_review_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "pr_to_po_demo_review_view", + "to_id": "view/pr_to_po_demo_review_view", + "collection": "governs", + "role": "governs", + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/requisition_approval_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "requisition_approval_view", + "to_id": "view/requisition_approval_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/sourcing_confirmation_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "sourcing_confirmation_view", + "to_id": "view/sourcing_confirmation_view", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/pr_to_po_def_v1", + "_to": "view/supplier_validation_view", + "from": "pr_to_po_def_v1", + "from_id": "version/pr_to_po_def_v1", + "to": "supplier_validation_view", + "to_id": "view/supplier_validation_view", + "collection": "governs", + "role": null, + "label": null + } + ], + "data_definitions": [ + { + "_id": "data/purchase_order_def", + "_key": "purchase_order_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Purchase Order data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "ready_to_send" + }, + { + "name": "dispatch_method", + "label": "Dispatch Method", + "type": "string", + "required": true, + "description": "Dispatch Method" + }, + { + "name": "supplier_sent_at", + "label": "Supplier Sent At", + "type": "datetime", + "required": false, + "description": "Supplier Sent At" + } + ], + "kind": "definition", + "label": "Purchase Order", + "name": "purchase_order_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/supplier_validation_def", + "_key": "supplier_validation_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Supplier Validation data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": true, + "description": "Supplier Reference" + }, + { + "name": "supplier_status", + "label": "Supplier Status", + "type": "string", + "required": true, + "description": "Supplier Status" + }, + { + "name": "payment_terms", + "label": "Payment Terms", + "type": "string", + "required": true, + "description": "Payment Terms" + }, + { + "name": "incoterms", + "label": "Incoterms", + "type": "string", + "required": false, + "description": "Incoterms" + }, + { + "name": "compliance_status", + "label": "Compliance Status", + "type": "string", + "required": true, + "description": "Compliance Status" + } + ], + "kind": "definition", + "label": "Supplier Validation", + "name": "supplier_validation_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/requisition_approval_def", + "_key": "requisition_approval_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Requisition Approval data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "manager_decision", + "label": "Manager Decision", + "type": "string", + "required": true, + "description": "Manager Decision" + }, + { + "name": "approval_comments", + "label": "Approval Comments", + "type": "textarea", + "required": false, + "description": "Approval Comments" + } + ], + "kind": "definition", + "label": "Requisition Approval", + "name": "requisition_approval_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/purchase_requisition_def", + "_key": "purchase_requisition_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Purchase Requisition data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "requester_department", + "label": "Requester Department", + "type": "string", + "required": true, + "description": "Requester Department" + }, + { + "name": "business_unit", + "label": "Business Unit", + "type": "string", + "required": true, + "description": "Business Unit" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "required_date", + "label": "Required Date", + "type": "date", + "required": true, + "description": "Required Date" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "tax_total", + "label": "Tax Total", + "type": "number", + "required": false, + "description": "Tax Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "justification", + "label": "Business Justification", + "type": "textarea", + "required": true, + "description": "Business Justification" + }, + { + "name": "attachments", + "label": "Attachments", + "type": "array", + "required": false, + "description": "Attachments" + } + ], + "kind": "definition", + "label": "Purchase Requisition", + "name": "purchase_requisition_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/po_sent_def", + "_key": "po_sent_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "PO Sent data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "sent_to_supplier" + }, + { + "name": "supplier_acknowledgement", + "label": "Supplier Acknowledgement", + "type": "string", + "required": true, + "description": "Supplier Acknowledgement" + }, + { + "name": "acknowledged_at", + "label": "Acknowledged At", + "type": "datetime", + "required": false, + "description": "Acknowledged At" + } + ], + "kind": "definition", + "label": "PO Sent", + "name": "po_sent_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/po_ready_def", + "_key": "po_ready_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "PO Ready data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "ready_to_send" + }, + { + "name": "release_checklist", + "label": "Release Checklist", + "type": "array", + "required": true, + "description": "Release Checklist" + }, + { + "name": "ready_approved_by", + "label": "Ready Approved By", + "type": "string", + "required": true, + "description": "Ready Approved By" + } + ], + "kind": "definition", + "label": "PO Ready", + "name": "po_ready_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/po_dispatch_def", + "_key": "po_dispatch_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "PO Dispatch data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "dispatch_method", + "label": "Dispatch Method", + "type": "string", + "required": true, + "description": "Dispatch Method" + }, + { + "name": "supplier_contact", + "label": "Supplier Contact", + "type": "string", + "required": true, + "description": "Supplier Contact" + }, + { + "name": "supplier_sent_at", + "label": "Supplier Sent At", + "type": "datetime", + "required": true, + "description": "Supplier Sent At" + }, + { + "name": "dispatch_evidence", + "label": "Dispatch Evidence", + "type": "array", + "required": false, + "description": "Dispatch Evidence" + } + ], + "kind": "definition", + "label": "PO Dispatch", + "name": "po_dispatch_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/po_change_cancel_def", + "_key": "po_change_cancel_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "PO Change or Cancellation data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number" + }, + { + "name": "change_type", + "label": "Change Type", + "type": "string", + "required": true, + "description": "Change Type" + }, + { + "name": "change_reason", + "label": "Change Reason", + "type": "textarea", + "required": true, + "description": "Change Reason" + }, + { + "name": "change_approval_status", + "label": "Change Approval Status", + "type": "string", + "required": true, + "description": "Change Approval Status" + }, + { + "name": "replacement_po_number", + "label": "Replacement PO Number", + "type": "string", + "required": false, + "description": "Replacement PO Number" + } + ], + "kind": "definition", + "label": "PO Change or Cancellation", + "name": "po_change_cancel_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/exception_review_def", + "_key": "exception_review_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Exception Review data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "exception_type", + "label": "Exception Type", + "type": "string", + "required": true, + "description": "Exception Type" + }, + { + "name": "exception_owner", + "label": "Exception Owner", + "type": "string", + "required": true, + "description": "Exception Owner" + }, + { + "name": "exception_decision", + "label": "Exception Decision", + "type": "string", + "required": true, + "description": "Exception Decision" + }, + { + "name": "approval_comments", + "label": "Approval Comments", + "type": "textarea", + "required": false, + "description": "Approval Comments" + } + ], + "kind": "definition", + "label": "Exception Review", + "name": "exception_review_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + }, + { + "_id": "data/budget_check_def", + "_key": "budget_check_def", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Budget Check data for PR-to-PO.", + "field_schemas": null, + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "budget_available", + "label": "Budget Available", + "type": "boolean", + "required": true, + "description": "Budget Available" + }, + { + "name": "approval_limit", + "label": "Approval Limit", + "type": "number", + "required": true, + "description": "Approval Limit" + }, + { + "name": "budget_check_result", + "label": "Budget Check Result", + "type": "string", + "required": true, + "description": "Budget Check Result" + }, + { + "name": "approval_route", + "label": "Approval Route", + "type": "string", + "required": true, + "description": "Approval Route" + } + ], + "kind": "definition", + "label": "Budget Check", + "name": "budget_check_def", + "natural_key": "request_number", + "primary_key": "request_number", + "source_context": "FM-E2E-PROC-EXEC-PR-PO-V1 executable seed", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": "1.0.0" + } + ], + "view_definitions": [ + { + "_id": "view/po_change_cancel_view", + "_key": "po_change_cancel_view", + "actions": [ + { + "label": "Submit", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Change or Cancel PO", + "layout": { + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number" + }, + { + "name": "change_type", + "label": "Change Type", + "type": "string", + "required": true, + "description": "Change Type" + }, + { + "name": "change_reason", + "label": "Change Reason", + "type": "textarea", + "required": true, + "description": "Change Reason" + }, + { + "name": "change_approval_status", + "label": "Change Approval Status", + "type": "string", + "required": true, + "description": "Change Approval Status" + }, + { + "name": "replacement_po_number", + "label": "Replacement PO Number", + "type": "string", + "required": false, + "description": "Replacement PO Number" + } + ], + "layout": "form" + }, + "name": "po_change_cancel_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/po_sent_view", + "_key": "po_sent_view", + "actions": [ + { + "label": "Confirm Sent", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "PO Sent", + "layout": { + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "sent_to_supplier" + }, + { + "name": "supplier_acknowledgement", + "label": "Supplier Acknowledgement", + "type": "string", + "required": true, + "description": "Supplier Acknowledgement" + }, + { + "name": "acknowledged_at", + "label": "Acknowledged At", + "type": "datetime", + "required": false, + "description": "Acknowledged At" + } + ], + "layout": "form" + }, + "name": "po_sent_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/po_dispatch_view", + "_key": "po_dispatch_view", + "actions": [ + { + "label": "Send", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Send PO", + "layout": { + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "dispatch_method", + "label": "Dispatch Method", + "type": "string", + "required": true, + "description": "Dispatch Method" + }, + { + "name": "supplier_contact", + "label": "Supplier Contact", + "type": "string", + "required": true, + "description": "Supplier Contact" + }, + { + "name": "supplier_sent_at", + "label": "Supplier Sent At", + "type": "datetime", + "required": true, + "description": "Supplier Sent At" + }, + { + "name": "dispatch_evidence", + "label": "Dispatch Evidence", + "type": "array", + "required": false, + "description": "Dispatch Evidence" + } + ], + "layout": "form" + }, + "name": "po_dispatch_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/po_ready_view", + "_key": "po_ready_view", + "actions": [ + { + "label": "Mark Ready", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "PO Ready", + "layout": { + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "ready_to_send" + }, + { + "name": "release_checklist", + "label": "Release Checklist", + "type": "array", + "required": true, + "description": "Release Checklist" + }, + { + "name": "ready_approved_by", + "label": "Ready Approved By", + "type": "string", + "required": true, + "description": "Ready Approved By" + } + ], + "layout": "form" + }, + "name": "po_ready_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/exception_review_view", + "_key": "exception_review_view", + "actions": [ + { + "label": "Approve Exception", + "action": "submit" + }, + { + "label": "Reject", + "action": "reject" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Review Exceptions", + "layout": { + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "exception_type", + "label": "Exception Type", + "type": "string", + "required": true, + "description": "Exception Type" + }, + { + "name": "exception_owner", + "label": "Exception Owner", + "type": "string", + "required": true, + "description": "Exception Owner" + }, + { + "name": "exception_decision", + "label": "Exception Decision", + "type": "string", + "required": true, + "description": "Exception Decision" + }, + { + "name": "approval_comments", + "label": "Approval Comments", + "type": "textarea", + "required": false, + "description": "Approval Comments" + } + ], + "layout": "form" + }, + "name": "exception_review_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/po_preparation_view", + "_key": "po_preparation_view", + "actions": [ + { + "label": "Submit", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Prepare PO", + "layout": { + "fields": [ + { + "name": "po_number", + "label": "Purchase Order Number", + "type": "string", + "required": true, + "description": "Purchase Order Number", + "default": "PO-DEV-READY" + }, + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "po_status", + "label": "Purchase Order Status", + "type": "string", + "required": true, + "description": "Purchase Order Status", + "default": "ready_to_send" + }, + { + "name": "dispatch_method", + "label": "Dispatch Method", + "type": "string", + "required": true, + "description": "Dispatch Method" + }, + { + "name": "supplier_sent_at", + "label": "Supplier Sent At", + "type": "datetime", + "required": false, + "description": "Supplier Sent At" + } + ], + "layout": "form" + }, + "name": "po_preparation_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/sourcing_confirmation_view", + "_key": "sourcing_confirmation_view", + "actions": [ + { + "label": "Submit", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Confirm Source", + "layout": { + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "requester_department", + "label": "Requester Department", + "type": "string", + "required": true, + "description": "Requester Department" + }, + { + "name": "business_unit", + "label": "Business Unit", + "type": "string", + "required": true, + "description": "Business Unit" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "required_date", + "label": "Required Date", + "type": "date", + "required": true, + "description": "Required Date" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "tax_total", + "label": "Tax Total", + "type": "number", + "required": false, + "description": "Tax Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "justification", + "label": "Business Justification", + "type": "textarea", + "required": true, + "description": "Business Justification" + }, + { + "name": "attachments", + "label": "Attachments", + "type": "array", + "required": false, + "description": "Attachments" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": true, + "description": "Supplier Reference" + }, + { + "name": "supplier_status", + "label": "Supplier Status", + "type": "string", + "required": true, + "description": "Supplier Status" + }, + { + "name": "payment_terms", + "label": "Payment Terms", + "type": "string", + "required": true, + "description": "Payment Terms" + }, + { + "name": "incoterms", + "label": "Incoterms", + "type": "string", + "required": false, + "description": "Incoterms" + }, + { + "name": "compliance_status", + "label": "Compliance Status", + "type": "string", + "required": true, + "description": "Compliance Status" + } + ], + "layout": "form" + }, + "name": "sourcing_confirmation_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/supplier_validation_view", + "_key": "supplier_validation_view", + "actions": [ + { + "label": "Submit", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Validate Supplier", + "layout": { + "fields": [ + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": true, + "description": "Supplier Reference" + }, + { + "name": "supplier_status", + "label": "Supplier Status", + "type": "string", + "required": true, + "description": "Supplier Status" + }, + { + "name": "payment_terms", + "label": "Payment Terms", + "type": "string", + "required": true, + "description": "Payment Terms" + }, + { + "name": "incoterms", + "label": "Incoterms", + "type": "string", + "required": false, + "description": "Incoterms" + }, + { + "name": "compliance_status", + "label": "Compliance Status", + "type": "string", + "required": true, + "description": "Compliance Status" + } + ], + "layout": "form" + }, + "name": "supplier_validation_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/requisition_approval_view", + "_key": "requisition_approval_view", + "actions": [ + { + "label": "Approve", + "action": "submit" + }, + { + "label": "Reject", + "action": "reject" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Approve Requisition", + "layout": { + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "manager_decision", + "label": "Manager Decision", + "type": "string", + "required": true, + "description": "Manager Decision" + }, + { + "name": "approval_comments", + "label": "Approval Comments", + "type": "textarea", + "required": false, + "description": "Approval Comments" + } + ], + "layout": "form" + }, + "name": "requisition_approval_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/budget_check_view", + "_key": "budget_check_view", + "actions": [ + { + "label": "Submit", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Check Budget", + "layout": { + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "budget_available", + "label": "Budget Available", + "type": "boolean", + "required": true, + "description": "Budget Available" + }, + { + "name": "approval_limit", + "label": "Approval Limit", + "type": "number", + "required": true, + "description": "Approval Limit" + }, + { + "name": "budget_check_result", + "label": "Budget Check Result", + "type": "string", + "required": true, + "description": "Budget Check Result" + }, + { + "name": "approval_route", + "label": "Approval Route", + "type": "string", + "required": true, + "description": "Approval Route" + } + ], + "layout": "form" + }, + "name": "budget_check_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/pr_intake_view", + "_key": "pr_intake_view", + "actions": [ + { + "label": "Submit", + "action": "submit" + } + ], + "channel": "web", + "created_at": "2026-06-10T11:22:41.031674+00:00", + "description": null, + "kind": "definition", + "label": "Create Requisition", + "layout": { + "fields": [ + { + "name": "requisition_id", + "label": "Requisition ID", + "type": "string", + "required": true, + "description": "Requisition ID" + }, + { + "name": "requester_name", + "label": "Requester Name", + "type": "string", + "required": true, + "description": "Requester Name" + }, + { + "name": "requester_department", + "label": "Requester Department", + "type": "string", + "required": true, + "description": "Requester Department" + }, + { + "name": "business_unit", + "label": "Business Unit", + "type": "string", + "required": true, + "description": "Business Unit" + }, + { + "name": "cost_center", + "label": "Cost Center", + "type": "string", + "required": true, + "description": "Cost Center" + }, + { + "name": "gl_account", + "label": "GL Account", + "type": "string", + "required": true, + "description": "GL Account" + }, + { + "name": "project_code", + "label": "Project Code", + "type": "string", + "required": false, + "description": "Project Code" + }, + { + "name": "required_date", + "label": "Required Date", + "type": "date", + "required": true, + "description": "Required Date" + }, + { + "name": "supplier_name", + "label": "Supplier Name", + "type": "string", + "required": true, + "description": "Supplier Name" + }, + { + "name": "supplier_reference", + "label": "Supplier Reference", + "type": "string", + "required": false, + "description": "Supplier Reference" + }, + { + "name": "currency", + "label": "Currency", + "type": "string", + "required": true, + "description": "Currency", + "default": "AED" + }, + { + "name": "line_items", + "label": "Line Items", + "type": "array", + "required": true, + "description": "Line Items" + }, + { + "name": "line_1_description", + "label": "Line 1 Description", + "type": "string", + "required": true, + "description": "Line 1 Description" + }, + { + "name": "line_1_quantity", + "label": "Line 1 Quantity", + "type": "number", + "required": true, + "description": "Line 1 Quantity" + }, + { + "name": "line_1_unit_price", + "label": "Line 1 Unit Price", + "type": "number", + "required": true, + "description": "Line 1 Unit Price" + }, + { + "name": "line_2_description", + "label": "Line 2 Description", + "type": "string", + "required": false, + "description": "Line 2 Description" + }, + { + "name": "line_2_quantity", + "label": "Line 2 Quantity", + "type": "number", + "required": false, + "description": "Line 2 Quantity" + }, + { + "name": "line_2_unit_price", + "label": "Line 2 Unit Price", + "type": "number", + "required": false, + "description": "Line 2 Unit Price" + }, + { + "name": "net_total", + "label": "Net Total", + "type": "number", + "required": true, + "description": "Net Total" + }, + { + "name": "tax_total", + "label": "Tax Total", + "type": "number", + "required": false, + "description": "Tax Total" + }, + { + "name": "gross_total", + "label": "Gross Total", + "type": "number", + "required": true, + "description": "Gross Total" + }, + { + "name": "justification", + "label": "Business Justification", + "type": "textarea", + "required": true, + "description": "Business Justification" + }, + { + "name": "attachments", + "label": "Attachments", + "type": "array", + "required": false, + "description": "Attachments" + } + ], + "layout": "form" + }, + "name": "pr_intake_view", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.149252+00:00", + "version": null + }, + { + "_id": "view/pr_to_po_demo_review_view", + "_key": "pr_to_po_demo_review_view", + "actions": [ + { + "action": "save_draft", + "label": "Save Draft" + } + ], + "channel": "web", + "created_at": "2026-06-10T07:51:37.645Z", + "description": "Minimal presentation view for T10 live runtime smoke.", + "kind": "definition", + "label": "Demo Manager Review", + "layout": { + "layout": "form", + "fields": [ + { + "name": "request_number", + "type": "string", + "required": true, + "label": "Request #", + "is_subject": true + }, + { + "name": "supplier", + "type": "string", + "required": true, + "label": "Supplier" + }, + { + "name": "total_amount", + "type": "number", + "required": true, + "label": "Amount" + }, + { + "name": "currency", + "type": "string", + "required": true, + "label": "Currency" + }, + { + "name": "status", + "type": "string", + "required": true, + "label": "Status" + } + ] + }, + "name": "pr_to_po_demo_review_view", + "source_context": "fm06-t10-demo-reset-v2", + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T07:51:37.645Z", + "version": 1 + } + ], + "rule_definitions": [ + { + "_id": "rule/po_change_cancel_rule", + "_key": "po_change_cancel_rule", + "content": "Change/cancel requires change reason, approval status, supplier notification, and replacement PO link when applicable.", + "created_at": "2026-06-10T11:22:42.027276+00:00", + "description": "Change/cancel requires change reason, approval status, supplier notification, and replacement PO link when applicable.", + "kind": "definition", + "label": "PO Change or Cancellation", + "name": "po_change_cancel_rule", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.262366+00:00", + "version": null + }, + { + "_id": "rule/po_release_rule", + "_key": "po_release_rule", + "content": "PO ready requires approved requisition, valid supplier, complete line items, currency, totals, required date, and dispatch method.", + "created_at": "2026-06-10T11:22:42.027276+00:00", + "description": "PO ready requires approved requisition, valid supplier, complete line items, currency, totals, required date, and dispatch method.", + "kind": "definition", + "label": "PO Release", + "name": "po_release_rule", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.262366+00:00", + "version": null + }, + { + "_id": "rule/supplier_compliance_rule", + "_key": "supplier_compliance_rule", + "content": "PO cannot be prepared unless supplier_status is active or supplier onboarding exception is approved.", + "created_at": "2026-06-10T11:22:42.027276+00:00", + "description": "PO cannot be prepared unless supplier_status is active or supplier onboarding exception is approved.", + "kind": "definition", + "label": "Supplier Compliance", + "name": "supplier_compliance_rule", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.262366+00:00", + "version": null + }, + { + "_id": "rule/budget_and_threshold_rule", + "_key": "budget_and_threshold_rule", + "content": "Route based on budget_available, approval_limit, cost center, GL/project coding, and gross_total.", + "created_at": "2026-06-10T11:22:42.027276+00:00", + "description": "Route based on budget_available, approval_limit, cost center, GL/project coding, and gross_total.", + "kind": "definition", + "label": "Budget and Threshold", + "name": "budget_and_threshold_rule", + "source_context": null, + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-13T18:09:08.262366+00:00", + "version": null + }, + { + "_id": "rule/pr_to_po_demo_review_rule", + "_key": "pr_to_po_demo_review_rule", + "content": "Demo smoke save-draft action is allowed for rehearsal validation.", + "created_at": "2026-06-10T07:51:37.645Z", + "description": "Marker rule used to classify the demo review step as runtime-ready for save-draft smoke validation.", + "kind": "definition", + "label": "Demo Review Rule", + "name": "pr_to_po_demo_review_rule", + "source_context": "fm06-t10-demo-reset-v2", + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T07:51:37.645Z", + "version": 1 + } + ], + "version_definitions": [ + { + "_id": "version/pr_to_po_def_v1", + "_key": "pr_to_po_def_v1", + "approved_at": "2026-06-10T07:51:37.645Z", + "approved_by": "demo.flow-master.ai", + "change_description": "FM06 demo reset seed", + "created_at": "2026-06-10T07:51:37.645Z", + "created_by": "demo.flow-master.ai", + "description": "Active demo reset version governing the procurement process and entities.", + "kind": "definition", + "label": "Purchase Requisition to PO v1", + "legal_entity": "a0000000-0000-0000-0000-000000000010", + "name": "pr_to_po_def v1", + "source_context": "fm06-t10-demo-reset-v2", + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T07:51:37.645Z", + "version": 1 + } + ] + }, + "headlineTx": "6be59bb639264608bccae3b55c93f9fa", + "headlineRt": { + "transaction_id": "6be59bb639264608bccae3b55c93f9fa", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "6be59bb639264608bccae3b55c93f9fa", + "business_subject": "Purchase Requisition to PO · 6be59bb6", + "status": "running", + "active_step": { + "step_run_id": "ea2-work-item-6be59bb639264608bccae3b55c93f9fa", + "step_definition_id": "pr_to_po_demo_review", + "display_name": "Demo Manager Review", + "dispatch_kind": null, + "form_fields": [ + { + "name": "request_number", + "type": "string", + "required": true, + "label": "Request #", + "is_subject": true + }, + { + "name": "supplier", + "type": "string", + "required": true, + "label": "Supplier" + }, + { + "name": "total_amount", + "type": "number", + "required": true, + "label": "Amount" + }, + { + "name": "currency", + "type": "string", + "required": true, + "label": "Currency" + }, + { + "name": "status", + "type": "string", + "required": true, + "label": "Status" + } + ], + "presentation_view_id": "pr_to_po_demo_review_view" + }, + "available_actions": [ + { + "id": "submit", + "display_label": "Submit", + "kind": "submit_view", + "actor_modes": [ + "direct_user", + "sidekick_on_behalf_of_user" + ], + "requires_values": true, + "requires_reason": false, + "enabled": true + } + ], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T14:10:28.841672+00:00", + "created_by": null + }, + "recent": [ + { + "transaction_id": "622329654050422c827d351c96ebea0a", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "622329654050422c827d351c96ebea0a", + "business_subject": "Purchase Requisition to PO #62232965", + "status": "completed", + "active_step": null, + "available_actions": [], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T08:02:16.338009+00:00", + "created_by": null + }, + { + "transaction_id": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "business_subject": "Purchase Requisition to PO · ab8d82e5", + "status": "draft", + "active_step": null, + "available_actions": [], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T03:25:49.888195+00:00", + "created_by": null + }, + { + "transaction_id": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "ab8d82e5-d8c8-4a72-95ba-515bac0ff82a", + "business_subject": "Purchase Requisition to PO · ab8d82e5", + "status": "draft", + "active_step": null, + "available_actions": [], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T03:25:49.888195+00:00", + "created_by": null + } + ] + }, + { + "id": "extra-1", + "family": { + "id": "extra-1", + "label": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "subtitle": "6 live cases", + "accent": "#64748b" + }, + "def_key": "51c8670228eb41899a20d05151d34eaa", + "def_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "hubs": [ + "procurement" + ], + "statuses": { + "running": 1, + "errored": 2, + "completed": 2, + "cancelled": 1 + }, + "cases": [ + { + "transaction_id": "43eedf3de1bf4f59b5659ba061b3424d", + "case_key": "43eedf3de1bf4f59b5659ba061b3424d", + "short_id": "43eedf3d", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #43eedf3d", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T14:03:07.152231+00:00", + "updated_at": "2026-06-11T19:45:48.832912+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "51c8670228eb41899a20d05151d34eaa_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "c0f20ec170d547948b311ffc4ba3393e", + "case_key": "c0f20ec170d547948b311ffc4ba3393e", + "short_id": "c0f20ec1", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #c0f20ec1", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "errored", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:27:09.602561+00:00", + "updated_at": "2026-06-11T19:45:48.589608+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "51c8670228eb41899a20d05151d34eaa_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "d3186a18e4024543aac95b488dab0d31", + "case_key": "d3186a18e4024543aac95b488dab0d31", + "short_id": "d3186a18", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #d3186a18", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:45:51.010865+00:00", + "updated_at": "2026-06-11T19:45:48.437701+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "bbf490377a7b4a5b96d58a6209157988", + "case_key": "bbf490377a7b4a5b96d58a6209157988", + "short_id": "bbf49037", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #bbf49037", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "completed", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:44:49.049854+00:00", + "updated_at": "2026-06-11T19:45:48.411092+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "51a6468172114096af5a877c06a56396", + "case_key": "51a6468172114096af5a877c06a56396", + "short_id": "51a64681", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #51a64681", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "cancelled", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:43:19.827037+00:00", + "updated_at": "2026-06-11T19:45:48.385741+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": null, + "active_step": null, + "active_step_display_name": null, + "next_action": "In progress", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "e1864722c3234958963bd2e97ef868c5", + "case_key": "e1864722c3234958963bd2e97ef868c5", + "short_id": "e1864722", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #e1864722", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "definition_name": "atlas-f1-fresh-20260610090945-9496", + "definition_key": "51c8670228eb41899a20d05151d34eaa", + "hub": "procurement", + "status": "errored", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-10T15:43:11.218770+00:00", + "updated_at": "2026-06-11T19:45:48.339863+00:00", + "age_days": 3, + "amount": null, + "currency": null, + "current_node": "51c8670228eb41899a20d05151d34eaa_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + } + ], + "graph": { + "process_definition": { + "_id": "flow/51c8670228eb41899a20d05151d34eaa", + "_key": "51c8670228eb41899a20d05151d34eaa", + "config": { + "org_id": "a0000000-0000-0000-0000-000000000010", + "executable": true, + "is_executable": true, + "nodes": [ + { + "id": "start", + "type": "start", + "label": "Request submitted" + }, + { + "id": "manager_review", + "type": "human_task", + "label": "Manager review", + "form_ref": "purchase_requisition_def", + "actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "complete" + } + ] + }, + { + "id": "approved", + "type": "end", + "label": "Approved" + } + ], + "edges": [ + { + "id": "start_to_review", + "source": "start", + "target": "manager_review" + }, + { + "id": "review_to_approved", + "source": "manager_review", + "target": "approved", + "outcome": "complete" + } + ] + }, + "created_at": "2026-06-10T09:09:46.475022+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Fresh F1 process lifecycle proof created through the FM06 process wizard EA2 contract.", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "hub": "procurement", + "kind": "definition", + "label": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496", + "name": "atlas-f1-fresh-20260610090945-9496", + "source_context": "atlas-f1-fresh-proof", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-11T14:54:32.338127+00:00", + "version": 1 + }, + "nodes": [ + { + "_id": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "_key": "51c8670228eb41899a20d05151d34eaa_approved", + "actions": [], + "config": { + "dispatch_kind": "end" + }, + "created_at": "2026-06-10T09:09:46.930752+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Fresh F1 proof terminal step.", + "display_name": "Approved", + "kind": "definition", + "label": "Approved", + "name": "51c8670228eb41899a20d05151d34eaa_approved", + "source_context": "atlas-f1-fresh-proof", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:09:46.930752+00:00", + "version": 1, + "form_fields": [], + "presentation_view_id": null, + "rule_ref": null, + "human_role": null, + "agent_capability": null, + "dispatch_kind": "end" + }, + { + "_id": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "_key": "51c8670228eb41899a20d05151d34eaa_manager_review", + "actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "submit_view", + "enabled": true + } + ], + "config": { + "dispatch_kind": "human" + }, + "created_at": "2026-06-10T09:09:46.930752+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Fresh F1 proof human review step.", + "dispatch_kind": "human", + "display_name": "Manager review", + "kind": "definition", + "label": "Manager review", + "name": "51c8670228eb41899a20d05151d34eaa_manager_review", + "source_context": "atlas-f1-fresh-proof", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:09:46.930752+00:00", + "version": 1, + "form_fields": [], + "presentation_view_id": null, + "rule_ref": null, + "human_role": null, + "agent_capability": null + } + ], + "edges": [ + { + "_from": "flow/51c8670228eb41899a20d05151d34eaa", + "_to": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "from": "51c8670228eb41899a20d05151d34eaa", + "from_id": "flow/51c8670228eb41899a20d05151d34eaa", + "to": "51c8670228eb41899a20d05151d34eaa_approved", + "to_id": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "_to": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "from": "51c8670228eb41899a20d05151d34eaa_manager_review", + "from_id": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "to": "51c8670228eb41899a20d05151d34eaa_approved", + "to_id": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "collection": "defines", + "role": "next", + "label": "complete" + }, + { + "_from": "flow/51c8670228eb41899a20d05151d34eaa", + "_to": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "from": "51c8670228eb41899a20d05151d34eaa", + "from_id": "flow/51c8670228eb41899a20d05151d34eaa", + "to": "51c8670228eb41899a20d05151d34eaa_manager_review", + "to_id": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "version/51c8670228eb41899a20d05151d34eaa_v1", + "_to": "flow/51c8670228eb41899a20d05151d34eaa", + "from": "51c8670228eb41899a20d05151d34eaa_v1", + "from_id": "version/51c8670228eb41899a20d05151d34eaa_v1", + "to": "51c8670228eb41899a20d05151d34eaa", + "to_id": "flow/51c8670228eb41899a20d05151d34eaa", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/51c8670228eb41899a20d05151d34eaa_v1", + "_to": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "from": "51c8670228eb41899a20d05151d34eaa_v1", + "from_id": "version/51c8670228eb41899a20d05151d34eaa_v1", + "to": "51c8670228eb41899a20d05151d34eaa_approved", + "to_id": "flow/51c8670228eb41899a20d05151d34eaa_approved", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/51c8670228eb41899a20d05151d34eaa_v1", + "_to": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "from": "51c8670228eb41899a20d05151d34eaa_v1", + "from_id": "version/51c8670228eb41899a20d05151d34eaa_v1", + "to": "51c8670228eb41899a20d05151d34eaa_manager_review", + "to_id": "flow/51c8670228eb41899a20d05151d34eaa_manager_review", + "collection": "governs", + "role": null, + "label": null + } + ], + "data_definitions": [], + "view_definitions": [], + "rule_definitions": [], + "version_definitions": [ + { + "_id": "version/51c8670228eb41899a20d05151d34eaa_v1", + "_key": "51c8670228eb41899a20d05151d34eaa_v1", + "approved_at": "2026-06-10T09:09:46.294Z", + "approved_by": "atlas-f1-fresh-proof", + "change_description": "Fresh F1 process lifecycle proof publish.", + "created_at": "2026-06-10T09:09:46.930752+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Governing version for the fresh F1 process lifecycle proof.", + "kind": "definition", + "label": "Atlas F1 Fresh 51c8670228eb41899a20d05151d34eaa v1", + "legal_entity": "a0000000-0000-0000-0000-000000000010", + "name": "51c8670228eb41899a20d05151d34eaa v1", + "source_context": "atlas-f1-fresh-proof", + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:09:46.930752+00:00", + "version": 1 + } + ] + }, + "headlineTx": "43eedf3de1bf4f59b5659ba061b3424d", + "headlineRt": { + "transaction_id": "43eedf3de1bf4f59b5659ba061b3424d", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "43eedf3de1bf4f59b5659ba061b3424d", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #43eedf3d", + "status": "running", + "active_step": { + "step_run_id": "ea2-work-item-43eedf3de1bf4f59b5659ba061b3424d", + "step_definition_id": "51c8670228eb41899a20d05151d34eaa_manager_review", + "display_name": "Manager review", + "dispatch_kind": null, + "form_fields": [], + "presentation_view_id": null + }, + "available_actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "submit_view", + "actor_modes": [ + "direct_user", + "sidekick_on_behalf_of_user" + ], + "requires_values": false, + "requires_reason": false, + "enabled": true + } + ], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T14:03:07.152231+00:00", + "created_by": null + }, + "recent": [ + { + "transaction_id": "c0f20ec170d547948b311ffc4ba3393e", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "c0f20ec170d547948b311ffc4ba3393e", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #c0f20ec1", + "status": "errored", + "active_step": { + "step_run_id": "ea2-work-item-c0f20ec170d547948b311ffc4ba3393e", + "step_definition_id": "51c8670228eb41899a20d05151d34eaa_manager_review", + "display_name": "Manager review", + "dispatch_kind": null, + "form_fields": [], + "presentation_view_id": null + }, + "available_actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "submit_view", + "actor_modes": [ + "direct_user", + "sidekick_on_behalf_of_user" + ], + "requires_values": false, + "requires_reason": false, + "enabled": true + } + ], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T03:27:09.602561+00:00", + "created_by": null + }, + { + "transaction_id": "d3186a18e4024543aac95b488dab0d31", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "d3186a18e4024543aac95b488dab0d31", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #d3186a18", + "status": "completed", + "active_step": null, + "available_actions": [], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-10T15:45:51.010865+00:00", + "created_by": null + }, + { + "transaction_id": "bbf490377a7b4a5b96d58a6209157988", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "bbf490377a7b4a5b96d58a6209157988", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090945-9496 #bbf49037", + "status": "completed", + "active_step": null, + "available_actions": [], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-10T15:44:49.049854+00:00", + "created_by": null + } + ] + }, + { + "id": "extra-2", + "family": { + "id": "extra-2", + "label": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "subtitle": "2 live cases", + "accent": "#64748b" + }, + "def_key": "ece34cd58fab4086a47cce25fd4d63b8", + "def_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "hubs": [ + "procurement" + ], + "statuses": { + "running": 1, + "errored": 1 + }, + "cases": [ + { + "transaction_id": "384fa003719d4675bc2fa2876c80f759", + "case_key": "384fa003719d4675bc2fa2876c80f759", + "short_id": "384fa003", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613 #384fa003", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "definition_name": "atlas-f1-fresh-20260610090831-2613", + "definition_key": "ece34cd58fab4086a47cce25fd4d63b8", + "hub": "procurement", + "status": "running", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-13T15:40:22.890538+00:00", + "updated_at": "2026-06-13T15:40:23.004508+00:00", + "age_days": 0, + "amount": null, + "currency": null, + "current_node": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + }, + { + "transaction_id": "750b2ea3226d4e10be14297ec909fc81", + "case_key": "750b2ea3226d4e10be14297ec909fc81", + "short_id": "750b2ea3", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613 #750b2ea3", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "definition_name": "atlas-f1-fresh-20260610090831-2613", + "definition_key": "ece34cd58fab4086a47cce25fd4d63b8", + "hub": "procurement", + "status": "errored", + "requester": null, + "requester_name": null, + "requester_display_name": null, + "created_at": "2026-06-11T03:27:08.186941+00:00", + "updated_at": "2026-06-11T19:45:48.539737+00:00", + "age_days": 2, + "amount": null, + "currency": null, + "current_node": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "active_step": null, + "active_step_display_name": "Manager review", + "next_action": "At step: Manager review", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "group": "in_progress" + } + ], + "graph": { + "process_definition": { + "_id": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "_key": "ece34cd58fab4086a47cce25fd4d63b8", + "config": { + "org_id": "a0000000-0000-0000-0000-000000000010", + "executable": true, + "is_executable": true, + "nodes": [ + { + "id": "start", + "type": "start", + "label": "Request submitted" + }, + { + "id": "manager_review", + "type": "human_task", + "label": "Manager review", + "form_ref": "purchase_requisition_def", + "actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "complete" + } + ] + }, + { + "id": "approved", + "type": "end", + "label": "Approved" + } + ], + "edges": [ + { + "id": "start_to_review", + "source": "start", + "target": "manager_review" + }, + { + "id": "review_to_approved", + "source": "manager_review", + "target": "approved", + "outcome": "complete" + } + ] + }, + "created_at": "2026-06-10T09:08:32.867996+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Fresh F1 process lifecycle proof created through the FM06 process wizard EA2 contract.", + "display_name": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "hub": "procurement", + "kind": "definition", + "label": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613", + "name": "atlas-f1-fresh-20260610090831-2613", + "source_context": "atlas-f1-fresh-proof", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:08:33.176726+00:00", + "version": 1 + }, + "nodes": [ + { + "_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "_key": "ece34cd58fab4086a47cce25fd4d63b8_approved", + "actions": [], + "config": { + "dispatch_kind": "end" + }, + "created_at": "2026-06-10T09:08:33.176726+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Fresh F1 proof terminal step.", + "display_name": "Approved", + "kind": "definition", + "label": "Approved", + "name": "ece34cd58fab4086a47cce25fd4d63b8_approved", + "source_context": "atlas-f1-fresh-proof", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:08:33.176726+00:00", + "version": 1, + "form_fields": [], + "presentation_view_id": null, + "rule_ref": null, + "human_role": null, + "agent_capability": null, + "dispatch_kind": "end" + }, + { + "_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "_key": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "submit_view", + "enabled": true + } + ], + "config": { + "dispatch_kind": "human" + }, + "created_at": "2026-06-10T09:08:33.176726+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Fresh F1 proof human review step.", + "dispatch_kind": "human", + "display_name": "Manager review", + "kind": "definition", + "label": "Manager review", + "name": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "source_context": "atlas-f1-fresh-proof", + "status": "published", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:08:33.176726+00:00", + "version": 1, + "form_fields": [], + "presentation_view_id": null, + "rule_ref": null, + "human_role": null, + "agent_capability": null + } + ], + "edges": [ + { + "_from": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "_to": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "from": "ece34cd58fab4086a47cce25fd4d63b8", + "from_id": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "to": "ece34cd58fab4086a47cce25fd4d63b8_approved", + "to_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "_to": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "from": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "from_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "to": "ece34cd58fab4086a47cce25fd4d63b8_approved", + "to_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "collection": "defines", + "role": "next", + "label": "complete" + }, + { + "_from": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "_to": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "from": "ece34cd58fab4086a47cce25fd4d63b8", + "from_id": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "to": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "to_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "collection": "defines", + "role": "child", + "label": null + }, + { + "_from": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "_to": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "from": "ece34cd58fab4086a47cce25fd4d63b8_v1", + "from_id": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "to": "ece34cd58fab4086a47cce25fd4d63b8", + "to_id": "flow/ece34cd58fab4086a47cce25fd4d63b8", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "_to": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "from": "ece34cd58fab4086a47cce25fd4d63b8_v1", + "from_id": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "to": "ece34cd58fab4086a47cce25fd4d63b8_approved", + "to_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_approved", + "collection": "governs", + "role": null, + "label": null + }, + { + "_from": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "_to": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "from": "ece34cd58fab4086a47cce25fd4d63b8_v1", + "from_id": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "to": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "to_id": "flow/ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "collection": "governs", + "role": null, + "label": null + } + ], + "data_definitions": [], + "view_definitions": [], + "rule_definitions": [], + "version_definitions": [ + { + "_id": "version/ece34cd58fab4086a47cce25fd4d63b8_v1", + "_key": "ece34cd58fab4086a47cce25fd4d63b8_v1", + "approved_at": "2026-06-10T09:08:32.539Z", + "approved_by": "atlas-f1-fresh-proof", + "change_description": "Fresh F1 process lifecycle proof publish.", + "created_at": "2026-06-10T09:08:33.176726+00:00", + "created_by": "a339524d-868e-4835-92de-2c26b9450b1d", + "description": "Governing version for the fresh F1 process lifecycle proof.", + "kind": "definition", + "label": "Atlas F1 Fresh ece34cd58fab4086a47cce25fd4d63b8 v1", + "legal_entity": "a0000000-0000-0000-0000-000000000010", + "name": "ece34cd58fab4086a47cce25fd4d63b8 v1", + "source_context": "atlas-f1-fresh-proof", + "status": "active", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "updated_at": "2026-06-10T09:08:33.176726+00:00", + "version": 1 + } + ] + }, + "headlineTx": "384fa003719d4675bc2fa2876c80f759", + "headlineRt": { + "transaction_id": "384fa003719d4675bc2fa2876c80f759", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "384fa003719d4675bc2fa2876c80f759", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613 #384fa003", + "status": "running", + "active_step": { + "step_run_id": "ea2-work-item-384fa003719d4675bc2fa2876c80f759", + "step_definition_id": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "display_name": "Manager review", + "dispatch_kind": null, + "form_fields": [], + "presentation_view_id": null + }, + "available_actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "submit_view", + "actor_modes": [ + "direct_user", + "sidekick_on_behalf_of_user" + ], + "requires_values": false, + "requires_reason": false, + "enabled": true + } + ], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-13T15:40:22.890538+00:00", + "created_by": null + }, + "recent": [ + { + "transaction_id": "750b2ea3226d4e10be14297ec909fc81", + "tenant_id": "a0000000-0000-0000-0000-000000000001", + "case_key": "750b2ea3226d4e10be14297ec909fc81", + "business_subject": "Atlas F1 Fresh atlas-f1-fresh-20260610090831-2613 #750b2ea3", + "status": "errored", + "active_step": { + "step_run_id": "ea2-work-item-750b2ea3226d4e10be14297ec909fc81", + "step_definition_id": "ece34cd58fab4086a47cce25fd4d63b8_manager_review", + "display_name": "Manager review", + "dispatch_kind": null, + "form_fields": [], + "presentation_view_id": null + }, + "available_actions": [ + { + "id": "complete", + "display_label": "Complete", + "kind": "submit_view", + "actor_modes": [ + "direct_user", + "sidekick_on_behalf_of_user" + ], + "requires_values": false, + "requires_reason": false, + "enabled": true + } + ], + "prefilled_values": {}, + "wait_detail": null, + "created_at": "2026-06-11T03:27:08.186941+00:00", + "created_by": null + } + ] + } + ] +} \ No newline at end of file diff --git a/src/scenes/Landing.tsx b/src/scenes/Landing.tsx new file mode 100644 index 0000000..7e95fc0 --- /dev/null +++ b/src/scenes/Landing.tsx @@ -0,0 +1,132 @@ +// Cinematic landing scene: brand, scenarios pick, start tour CTA. +import { motion } from "framer-motion"; +import { useApp } from "../state/store"; +import { liveMeta } from "../data/scenarios"; +import { Sparkles, Arrow, Cmd, Bot, Pulse } from "../components/icons"; + +export default function Landing() { + const setScene = useApp((s) => s.setScene); + const setScenarioId = useApp((s) => s.setScenarioId); + const startTour = useApp((s) => s.startTour); + const setCmdOpen = useApp((s) => s.setCmdOpen); + const scenarios = useApp((s) => s.scenarios); + const mode = useApp((s) => s.mode); + const setMode = useApp((s) => s.setMode); + const liveLoading = useApp((s) => s.liveLoading); + const liveTotals = useApp((s) => s.liveTotals); + + return ( +
+
+
+ +
+
+ + FlowMaster + + Mission Control +
+ +
+ +
+ + Business-as-code · Mission Control +

+ Every process. One control surface. +

+

+ FlowMaster turns the operational map of a company into living, + typed processes — backed by humans, agents, and rules — and gives you a + single command-center to drive them. Procurement scenarios are real, + backed by EA2 on{" "} + {liveMeta.fetchedFrom?.replace("https://", "") ?? "demo"}; + AR, HCM, GL, and Service are industry blueprints showing how this + same shell extends to any process family. +

+
+ + + +
+ +
+
+ + {liveTotals?.workItems ?? liveMeta.workItems} + {mode === "live" ? "live work items (now)" : "snapshot work items"} +
+
+ {liveTotals?.distinctDefs ?? liveMeta.distinctDefs} + process definitions +
+
+ + {scenarios.length} + scenarios in catalog +
+
+ {mode === "live" ? "LIVE" : "SNAPSHOT"} + data mode +
+
+
+ + + {scenarios.map((s) => ( + + ))} + +
+ +
+ FlowMaster · Mission Control demo · synthesised on top of demo.flow-master.ai +
+
+ ); +} diff --git a/src/scenes/MissionControl.tsx b/src/scenes/MissionControl.tsx new file mode 100644 index 0000000..0dadc59 --- /dev/null +++ b/src/scenes/MissionControl.tsx @@ -0,0 +1,72 @@ +// MissionControl scene: scenario tabs + graph + rails + telemetry strip. +import { useApp, scenarioById } from "../state/store"; +import ProcessGraph from "../components/ProcessGraph"; +import LeftRail from "../components/LeftRail"; +import Inspector from "../components/Inspector"; +import Telemetry from "../components/Telemetry"; + +export default function MissionControl() { + const scenarioId = useApp((s) => s.scenarioId); + const setScenarioId = useApp((s) => s.setScenarioId); + const scenarios = useApp((s) => s.scenarios); + const liveLoading = useApp((s) => s.liveLoading); + const liveError = useApp((s) => s.liveError); + const sc = scenarioById(scenarioId); + + return ( +
+ {liveLoading && ( +
+ Fetching live scenarios from demo.flow-master.ai… +
+ )} + {liveError && ( +
+ Live mode failed: {liveError} · showing snapshot +
+ )} +
+ {scenarios.map((s) => ( + + ))} +
+ +
+
+
{sc?.family.subtitle}
+

{sc?.defName}

+
{sc?.tagline}
+
+
+ {sc?.kpis.slice(0, 4).map((k) => ( +
+
{k.value}
+
{k.label}
+
+ ))} +
+
+ +
+ +
+ +
+ +
+ + +
+ ); +} diff --git a/src/scenes/RunHistory.tsx b/src/scenes/RunHistory.tsx new file mode 100644 index 0000000..03db4bf --- /dev/null +++ b/src/scenes/RunHistory.tsx @@ -0,0 +1,81 @@ +// RunHistory scene: cross-scenario timeline. +import { useMemo, useState } from "react"; +import { useApp } from "../state/store"; +import { Clock, History } from "../components/icons"; + +const STATUS_FILTERS = ["all", "running", "completed", "errored", "queued"] as const; +type Status = (typeof STATUS_FILTERS)[number]; + +const STATUS_COLOR: Record = { + running: "var(--run)", + completed: "var(--ok)", + done: "var(--ok)", + errored: "var(--block)", + failed: "var(--block)", + queued: "var(--queue)", +}; + +export default function RunHistory() { + const [filter, setFilter] = useState("all"); + const scenarios = useApp((s) => s.scenarios); + + const rows = useMemo(() => { + const out: Array<{ scenarioId: string; scenarioLabel: string; accent: string; live: boolean; run: (typeof scenarios)[number]["runs"][number] }> = []; + for (const s of scenarios) { + for (const r of s.runs) { + if (filter !== "all" && r.status !== filter && !(filter === "completed" && r.status === "done")) continue; + out.push({ scenarioId: s.id, scenarioLabel: s.family.label, accent: s.family.accent, live: s.live, run: r }); + } + } + return out.sort((a, b) => (b.run.startedAt || "").localeCompare(a.run.startedAt || "")); + }, [filter]); + + const maxDuration = useMemo(() => Math.max(60, ...rows.map((r) => r.run.durationSec)), [rows]); + + return ( +
+
+
+ Run history +

All scenarios · all runs

+
+ +
+ +
+ {rows.length === 0 &&
No runs match the current filter.
} + {rows.map((row) => ( +
+
+ + {row.run.shortId} + {row.live ? "live" : "bp"} +
+
{row.scenarioLabel}
+
{row.run.activeStep ?? "—"}
+
+
+
+
+ {Math.round(row.run.durationSec / 60)}m + {row.run.status} +
+
+ ))} +
+
+ ); +} diff --git a/src/state/store.ts b/src/state/store.ts new file mode 100644 index 0000000..a801f1d --- /dev/null +++ b/src/state/store.ts @@ -0,0 +1,185 @@ +// Global UI state for Mission Control. +import { create } from "zustand"; +import { liveScenarios as snapshotLive } from "../data/live"; +import { syntheticScenarios } from "../data/synthetic"; +import { buildLiveScenariosFromApi } from "../lib/buildScenarios"; +import { api } from "../lib/api"; +import type { ProcessScenario } from "../data/types"; + +export type SceneId = "landing" | "mission" | "history" | "studio"; +export type DataMode = "snapshot" | "live"; + +interface TourState { + active: boolean; + index: number; + autoplay: boolean; +} + +export interface Toast { + id: number; + kind: "info" | "ok" | "warn" | "err"; + msg: string; +} + +interface AppState { + scene: SceneId; + setScene: (s: SceneId) => void; + + /** snapshot = bundled scenarios.json; live = in-browser API client */ + mode: DataMode; + setMode: (m: DataMode) => Promise; + + liveLoading: boolean; + liveError: string | null; + liveTotals: { workItems: number; distinctDefs: number } | null; + liveFetchedAt: number | null; + + scenarios: ProcessScenario[]; + + scenarioId: string; + setScenarioId: (id: string) => void; + + selectedStepId: string | null; + setSelectedStepId: (id: string | null) => void; + + cmdOpen: boolean; + setCmdOpen: (v: boolean) => void; + + tour: TourState; + startTour: () => void; + endTour: () => void; + tourPrev: () => void; + tourNext: () => void; + tourSetIndex: (i: number) => void; + setTourAutoplay: (v: boolean) => void; + + recents: string[]; + pushRecent: (label: string) => void; + + inspectorTab: "overview" | "rules" | "evidence" | "raw" | "runs"; + setInspectorTab: (t: AppState["inspectorTab"]) => void; + + toasts: Toast[]; + pushToast: (kind: Toast["kind"], msg: string) => void; + dismissToast: (id: number) => void; +} + +const SNAPSHOT_SCENARIOS: ProcessScenario[] = [...snapshotLive, ...syntheticScenarios]; +const initialScenario = SNAPSHOT_SCENARIOS[0]; + +let toastSeq = 0; + +export const useApp = create((set, get) => ({ + scene: "landing", + setScene: (scene) => set({ scene }), + + mode: "snapshot", + setMode: async (mode) => { + if (mode === get().mode) return; + if (mode === "snapshot") { + set({ mode: "snapshot", scenarios: SNAPSHOT_SCENARIOS, liveError: null, liveLoading: false }); + get().pushToast("info", "Switched to snapshot mode (bundled JSON)"); + return; + } + set({ mode: "live", liveLoading: true, liveError: null }); + try { + const ping = await api.ping(); + if (!ping.ok) throw new Error(ping.reason || "backend unreachable"); + const { scenarios, workItems, distinctDefs } = await buildLiveScenariosFromApi(); + const merged = [...scenarios, ...syntheticScenarios]; + const first = merged[0]; + set({ + scenarios: merged, + liveTotals: { workItems: workItems.length, distinctDefs }, + liveFetchedAt: Date.now(), + liveLoading: false, + scenarioId: first?.id ?? get().scenarioId, + selectedStepId: first?.defaultStepId ?? null, + }); + get().pushToast("ok", `Live mode · ${scenarios.length} live + ${syntheticScenarios.length} blueprint scenarios`); + } catch (e) { + set({ liveLoading: false, liveError: (e as Error).message, mode: "snapshot", scenarios: SNAPSHOT_SCENARIOS }); + get().pushToast("err", `Live mode failed: ${(e as Error).message.slice(0, 80)} — falling back to snapshot`); + } + }, + + liveLoading: false, + liveError: null, + liveTotals: null, + liveFetchedAt: null, + + scenarios: SNAPSHOT_SCENARIOS, + + scenarioId: initialScenario?.id ?? "", + setScenarioId: (id) => { + const sc = get().scenarios.find((s) => s.id === id); + set({ + scenarioId: id, + selectedStepId: sc?.defaultStepId ?? null, + }); + if (sc) get().pushRecent(`Scenario: ${sc.family.label}`); + }, + + selectedStepId: initialScenario?.defaultStepId ?? null, + setSelectedStepId: (id) => set({ selectedStepId: id }), + + cmdOpen: false, + setCmdOpen: (cmdOpen) => set({ cmdOpen }), + + tour: { active: false, index: 0, autoplay: false }, + startTour: () => { + const sc = get().scenarios.find((s) => s.id === get().scenarioId); + const first = sc?.tour[0]; + set({ + tour: { active: true, index: 0, autoplay: false }, + scene: "mission", + selectedStepId: first?.selectStep ?? get().selectedStepId, + }); + }, + endTour: () => set({ tour: { active: false, index: 0, autoplay: false } }), + tourPrev: () => + set((s) => { + const sc = s.scenarios.find((sc) => sc.id === s.scenarioId); + const idx = Math.max(0, s.tour.index - 1); + const step = sc?.tour[idx]; + return { + tour: { ...s.tour, index: idx }, + selectedStepId: step?.selectStep ?? s.selectedStepId, + }; + }), + tourNext: () => + set((s) => { + const sc = s.scenarios.find((sc) => sc.id === s.scenarioId); + if (!sc) return s; + const last = sc.tour.length - 1; + const idx = Math.min(last, s.tour.index + 1); + const step = sc.tour[idx]; + const nextScenarioId = step?.switchToScenario ?? s.scenarioId; + return { + tour: { ...s.tour, index: idx }, + scenarioId: nextScenarioId, + selectedStepId: step?.selectStep ?? s.selectedStepId, + }; + }), + tourSetIndex: (i) => set((s) => ({ tour: { ...s.tour, index: i } })), + setTourAutoplay: (v) => set((s) => ({ tour: { ...s.tour, autoplay: v } })), + + recents: [], + pushRecent: (label) => + set((s) => ({ recents: [label, ...s.recents.filter((r) => r !== label)].slice(0, 8) })), + + inspectorTab: "overview", + setInspectorTab: (inspectorTab) => set({ inspectorTab }), + + toasts: [], + pushToast: (kind, msg) => { + const id = ++toastSeq; + set((s) => ({ toasts: [...s.toasts, { id, kind, msg }] })); + setTimeout(() => get().dismissToast(id), 4200); + }, + dismissToast: (id) => + set((s) => ({ toasts: s.toasts.filter((t) => t.id !== id) })), +})); + +export const scenarioById = (id: string): ProcessScenario | undefined => + useApp.getState().scenarios.find((s) => s.id === id); diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..0d272e5 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "es2023", + "lib": ["ES2023", "DOM"], + "module": "esnext", + "types": ["vite/client"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..d3c52ea --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "es2023", + "lib": ["ES2023"], + "module": "esnext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..7dc9434 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// Proxy /api/* to the demo.flow-master.ai backend during dev so live-mode +// fetches don't hit CORS. In production, the build is deployed under the +// same origin as the backend, so no proxy is needed. +const TARGET = process.env.VITE_FM_BASE || 'https://demo.flow-master.ai' + +export default defineConfig({ + plugins: [react()], + server: { + proxy: { + '/api': { + target: TARGET, + changeOrigin: true, + secure: true, + }, + }, + }, +})