Three Oracle-flagged gaps:
1. Studio createDraft 500 (was masked by retries). Empirical curl
reproducer proved POST /api/ea2/flow returns 201 with the minimal
shape but intermittently 500s when config.wizard.* is in the
initial body. Split: POST creates the draft minimally, then a
follow-up PUT attaches the wizard config best-effort. Draft
creation now lands reliably.
2. LLM 'temporarily unavailable' was a dead end for the user. Now
the assistant returns ok:true with a concrete menu of tools the
user CAN use right now ('list processes', 'start <name>',
'open <hub>', 'tell <name> that ...', 'remember ...', 'recall ...').
The reply renders as a normal assistant message, not a red error.
3. Topbar UI/UX Pro Max pass:
- Added aria-label to the ⌘K and avatar buttons (icon-only a11y)
- Removed the duplicate topbar-mid chips on Mission (Mission scene
already shows family/defName/version inline). Cleaner topbar.
- Added focus-visible outlines (2px amber, 2px offset) on all
topbar action buttons + user-menu items
- Hover/active scale on the avatar (1.04 / 0.97) with 160ms ease
- Tabular numerals for the ⌘K kbd and notification badge
- prefers-reduced-motion respected
30/30 vitest pass. tsc + vite build green.
POST /api/ea2/flow currently returns 500 after 19s on demo upstream.
Retry once with backoff, then surface a clear 'EA2 backend temporarily
unable to create new processes' message naming the status. The user
gets actionable info instead of a raw 500.
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.
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.
Backend EA2 apply-batch requires a request_id (idempotency key). Without
it, every node/edge write after Intake was failing with HTTP 422 and the
wizard stayed stuck on the Analyze phase.
Verified via qa/audit_wizard_writes.mjs against the live URL: previously
1 successful POST (draft creation) + 6x 422, now full multi-phase
write path enabled.