The Wizard already has the progress stepper with checkmarks, the
preview pane, and the review summary card before Publish. The
remaining gap from the UX overhaul was that the preview pane showed
the same flat list regardless of phase. Specialise it:
- Analyze + onward: graph-style vertical chain with dispatch-kind
bubbles (manual / assistant / system) and connector edges, so the
operator sees the flow as a graph not a list.
- Generate + onward: form preview that renders disabled input/select
controls for each named field, so the operator sees what end users
will fill in.
- Validate + onward: rules list (unchanged).
- Draft saved: all three render together so the review card has the
full picture beside it.
EA2 write contract is unchanged — createDraft / applyBatch /
publishFlow still fire at every phase transition. 31/31 vitest pass.
Close Oracle's two standing caveats so they can't gate a future loop:
1. Wizard dispatch label 'Person' was vague (Oracle: could imply chat
recipient, not work-routing). Now 'Manual review' in both dropdown
and preview-pane badge. dispatch_kind storage value unchanged
('human'/'agent'/'system' for EA2).
2. Chat unread cold-start. Topbar badge depended entirely on
localStorage being populated by Chat scene's first visit. Fresh
browser / private window / cleared storage saw 0 unread until then.
Added seedHeadsIfMissing in App.tsx topbar poll: on first refresh
(and only when localStorage heads count < thread count), fetches
last message per thread ONCE and persists to localStorage. Subsequent
ticks reuse the cache — same idle-poll budget (test still PASS).
Oracle PASS-with-caveats; closing all 3:
1. Wizard dispatch labels were 'human'/'agent'/'system' (impl-ish).
Now 'Person'/'Assistant'/'System' in both the dropdown and the
preview-pane badge.
2. Chat badge was thread COUNT (a buyer with 5 chats sees '5' forever).
Now real unread count, computed locally from localStorage heads +
read maps that the Chat scene already persists. App.tsx topbar
poll still only fires 2 network calls (listThreads + workItems);
per-thread unread math is zero-network.
3. LeftRail toast leaked 'POST /api/runtime/transactions/{id}/actions/
submit' / save_draft. Rewritten as 'Switch to live mode and sign
in to submit this action against EA2.'
Plus engineering-string sweep elsewhere: 'demo.flow-master.ai' /
'bundled JSON' / 'in-browser fetch' references removed from:
- App.tsx mode toggle title
- MissionControl loading spinner
- Landing mode-button title
- state/store snapshot toast
- data/live.ts + data/synthetic.ts tour-step bodies
- buildScenarios.ts tagline
Source-grep confirms no remaining user-visible engineering jargon
referencing the backend hostname or raw endpoints.
User brief: 'recreate dev.flow-master.ai Process Creation Wizard'.
Until now the Wizard wrote EA2 correctly but felt like a form. New:
- Stepper shows checkmarks on past steps (was just step numbers).
Step labels rewritten in human language: Describe / Steps / Form
fields / Rules / Review / Done.
- Sticky preview pane on the right shows the live process taking
shape: name + purpose + step chain (numbered + dispatch-kind
badges) + form field list + rules list. Collapses to a single
column at <=1000px.
- Analyze phase: each step gets up/down arrows + remove. New
'Add step' button.
- Generate phase: clearer placeholder ('e.g. requester name'), Yes/No
type label.
- Validate phase: friendlier placeholder.
- Review (Draft saved) phase: replaced the 3-number summary card
with a labelled review-row table that shows process name, purpose,
step chain, field count, rule count.
- Removed all the 'title=POST /api/...' attribute leaks that exposed
endpoint paths on hover.
- Helper functions: moveStep / removeStep / addStep keep node order
intact so the EA2 child-edge chain stays correct.
EA2 write contract unchanged: same 5 phases (Intake / Analyze /
Generate / Validate / Draft saved / Publish), same wizardApi.ops
emit shape, same per-phase apply-batch + governs edge.
Three Oracle round-7 caveats:
1. Wizard view replacement now deletes old presentation edges before
creating new field-based ones. Previously handleDataSave added new
edges additively, so runtime could still hit the generic Notes view.
2. Chat sidebar QA assertion was vacuously true (previewRows >= 0 &&
timeBadges >= 0). Now: when threads exist, preview count must equal
thread count AND at least one relative timestamp must render.
3. Agent composer placeholder rebranded from 'Ask Pi...' to 'Ask the
assistant...'. Closes residual Pi/LLM framing leak.
Oracle round-7 remediation, items 2 + 7:
- flowCuration.NON_BUSINESS_SOURCE_CONTEXTS no longer lists
EA2_DRAFT_PROCESS:process_creation (it's in STARTABLE_SOURCE_CONTEXTS).
Adds CANVAS_AGENT_MEMORY + CANVAS_AGENT_VAULT_ROOT to NON_BUSINESS so
vault docs never leak into hubs / catalogue.
- wizardApi.createView now accepts a fields list and emits proper field
defs (name slug, label, type from {string,number,boolean,textarea}).
- Wizard.handleDataSave rebuilds every step's view with the user's
draft.fields after Generate phase, then rewires the presentation
edges to the new views. Steps now expose real business fields, not a
generic 'Notes' textarea.
Reverse-engineered the EA2 runtime startability contract by diffing
pr_to_po_def (startable) against wizard-created drafts (500). Minimum
shape required:
Parent flow (kind=definition, status=published)
+ Step flow (kind=definition, status=published, dispatch_kind=human)
+ View doc (kind=definition, status=active, layout={fields,layout:form})
+ Version doc (kind=definition, status=active)
+ defines edge: parent -> step (role=child)
+ defines edge: step -> step (role=dispatch self-edge)
+ defines edge: step -> view (role=presentation)
+ governs edge collection 'governs': version -> parent (role=governs)
wizardApi.ops gains: createView, createVersion, childEdge, dispatchEdge,
presentationEdge, governsEdge. createStepEdge renamed to childEdge to
reflect the actual EA2 role. Steps now create with status=published
(was draft) so they're visible to the runtime.
Wizard.handleStructureSave emits all of the above in two apply-batches
(creates then wires). Verified live: posted a probe flow with this
contract, /api/runtime/transactions returned 200 + a running
transaction with step_run_id.
Oracle remediation batch 1 — closing gaps #1 (agent overclaim), #4
(demo-data leak), #5 (raw-ID exposure):
- src/lib/flowCuration.ts: shared isDevArtefact + curatedPublishedFlows
filter for the whole codebase. Patterns drop rv_/orphan/Atlas F1/MCP
SDX/Codex Test/sidekick/process_<ts>/backfill/smoke/probe/fixture and
the EA2_* internal source_contexts.
- src/scenes/Hub.tsx: loadPublishedFlows uses the shared curator
- src/lib/agentTools.ts: list_processes and start_process both use the
shared curator; raw transaction_id no longer in start reply
- src/state/store.ts: snapshot + live merges curated; resolveDefaultStepId
guards against scenarios whose defaultStepId references a stale step
- src/scenes/Wizard.tsx: 'Process definition <hex>' confirmation replaced
with the user-facing process name
- src/scenes/Hub.tsx: start toast no longer shows transaction_id prefix
- src/scenes/Agent.tsx + App.tsx + Landing.tsx: rename Pi -> FlowMaster
Command Assistant. Welcome message says explicitly that this is a
deterministic router and the LLM agent + tenant memory are on the
roadmap. Tab label, hub chip, turn author all rebranded.
- src/scenes/GeoAttendance.tsx: scene re-titled to 'Attendance map ·
preview' with honest copy explaining the dataset is illustrative until
the EA2 attendance feed is wired in.
- src/data/synthetic.ts: orphaned from runtime (kept in tree for tests).
Snapshot now sources only the live-cached EA2 read (scenarios.json),
filtered through the same curator.
29/29 tests green. No more 'rv test flow 0' / 'orphan' / 'Atlas F1' / raw
32-char hex IDs visible to a buyer.
EA2's apply-batch doc collections are restricted to ['data','flow','rule',
'version','view']; there is no 'ea2_node'. Steps are themselves 'flow'
documents (kind='definition') linked to the parent flow via the 'defines'
edge collection with role='next' (or 'presentation').
handleStructureSave now does two batches:
1) create N step flows, capture server-assigned keys
2) wire parent->step1->...->stepN with create_edge on 'defines'
Wizard was sending ops in the SDX-era shape:
{ collection, op: 'insert', flow_key, _key, ... }
with actor + flow_key duplicated at the request root.
Real EA2 contract (verified against ea2.baseline.svc/openapi.json):
POST /api/ea2/apply-batch
body: { request_id (8..128), ops: BatchOp[] (1..500), description? }
additionalProperties=false at request root
ops are a discriminated union by 'op':
create / update / delete (nodes by coll+key+data)
create_edge / delete_edge (edges by edge_coll+from+to)
actor/tenant resolved from Bearer token, not body.
Adds typed CreateOp/UpdateOp/DeleteOp/CreateEdgeOp/DeleteEdgeOp + wizardApi.ops
helpers (createNode, createEdge, publishFlow) so call sites don't have to
remember the discriminator shape.
Wizard.handleStructureSave + handlePublish updated to use the helpers.