From cc037a149e8ace915c275ca85240b388829fe030 Mon Sep 17 00:00:00 2001 From: shad Date: Sun, 14 Jun 2026 15:07:57 +0400 Subject: [PATCH] fix(oracle-r4): curation contradiction + wizard view enrichment 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. --- src/lib/flowCuration.ts | 3 ++- src/lib/wizardApi.ts | 20 +++++++++++++------- src/scenes/Wizard.tsx | 18 +++++++++++++++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/lib/flowCuration.ts b/src/lib/flowCuration.ts index c9b9897..7a988ef 100644 --- a/src/lib/flowCuration.ts +++ b/src/lib/flowCuration.ts @@ -30,10 +30,11 @@ const NON_BUSINESS_SOURCE_CONTEXTS = new Set([ "CANVAS_CHAT_INBOX", "CANVAS_ATTENDANCE_ROOT", "CANVAS_ATTENDANCE_SITE", + "CANVAS_AGENT_MEMORY", + "CANVAS_AGENT_VAULT_ROOT", "CANVAS_SEED_PROCESS", "CANVAS_SEED_STEP", "EA2_WIZARD_STEP", - "EA2_DRAFT_PROCESS:process_creation", ]); export const STARTABLE_FLOW_KEYS = new Set([ diff --git a/src/lib/wizardApi.ts b/src/lib/wizardApi.ts index 209bfa7..89fb107 100644 --- a/src/lib/wizardApi.ts +++ b/src/lib/wizardApi.ts @@ -139,9 +139,20 @@ export const wizardApi = { }, }; }, - createView(node: { display_name: string }): CreateOp { + createView(node: { display_name: string; fields?: { name: string; type: string }[] }): CreateOp { const slug = node.display_name.toLowerCase().replace(/[^a-z0-9]+/g, "_").slice(0, 30) || "view"; const name = `${slug}_view_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`; + const TYPE_MAP: Record = { string: "string", number: "number", boolean: "boolean", textarea: "textarea" }; + const fieldDefs = + node.fields && node.fields.length > 0 + ? node.fields + .filter((f) => f.name && f.name.trim()) + .map((f) => { + const fieldSlug = f.name.toLowerCase().replace(/[^a-z0-9]+/g, "_").slice(0, 40); + const label = f.name.charAt(0).toUpperCase() + f.name.slice(1); + return { name: fieldSlug, label, type: TYPE_MAP[f.type] || "string", required: true, description: label }; + }) + : [{ name: "notes", label: "Notes", type: "textarea", required: false, description: "Notes for this step" }]; return { op: "create", coll: "view", @@ -153,12 +164,7 @@ export const wizardApi = { description: null, source_context: null, channel: "web", - layout: { - layout: "form", - fields: [ - { name: "notes", label: "Notes", type: "textarea", required: false, description: "Notes" }, - ], - }, + layout: { layout: "form", fields: fieldDefs }, actions: [{ label: "Submit", action: "submit" }], }, }; diff --git a/src/scenes/Wizard.tsx b/src/scenes/Wizard.tsx index c018149..72ab3cb 100644 --- a/src/scenes/Wizard.tsx +++ b/src/scenes/Wizard.tsx @@ -144,13 +144,25 @@ export default function Wizard() { if (!draft.flowKey || !actor) return; setWorking(true); try { - // In a real app we'd save proper data models here. - // For the spike we just move forward and do a dummy update await wizardApi.updateDraftConfig(draft.flowKey, { config: { wizard: { panelState: { fields: draft.fields } } } }); + + if (draft.fields.length > 0 && draft.nodes.length > 0) { + const replaceOps: BatchOperation[] = draft.nodes.map(n => + wizardApi.ops.createView({ display_name: n.display_name, fields: draft.fields }) + ); + const res = await wizardApi.applyBatch(draft.flowKey, replaceOps, actor); + const newViewKeys = (res?.result?.ops || []).map((o: any) => o.key); + const wireOps: BatchOperation[] = draft.nodes.map((n, i) => + wizardApi.ops.presentationEdge(n._key, newViewKeys[i]) + ); + if (wireOps.length) await wizardApi.applyBatch(draft.flowKey, wireOps, actor); + updateDraft({ nodes: draft.nodes.map((n, i) => ({ ...n, viewKey: newViewKeys[i] })) }); + } + updateDraft({ step: "Validate" }); - pushToast("ok", "Data requirements saved"); + pushToast("ok", `Saved ${draft.fields.length} fields onto every step's form`); } catch (err: any) { pushToast("err", `Save failed: ${err.message}`); } finally {