From a11545d14202e9f64cf5c7321c31a559ec509128 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Wed, 18 Feb 2026 01:59:44 -0500 Subject: [PATCH] feat: block publish if unresolved answer stub nodes exist Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/pages/TreeEditorPage.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/TreeEditorPage.tsx b/frontend/src/pages/TreeEditorPage.tsx index 37ff1638..d21fd4f1 100644 --- a/frontend/src/pages/TreeEditorPage.tsx +++ b/frontend/src/pages/TreeEditorPage.tsx @@ -5,7 +5,7 @@ import { Undo2, Redo2, Save, CheckCircle2, Monitor, FileText, Code2, LayoutList, import { getMonacoEditor } from '@/components/tree-editor/code-mode' import { treesApi } from '@/api/trees' import { treeMarkdownApi } from '@/api/treeMarkdown' -import type { TreeCreate, TreeUpdate, TreeStatus } from '@/types' +import type { TreeCreate, TreeUpdate, TreeStatus, TreeStructure } from '@/types' import { useTreeEditorStore, useTreeEditorTemporal } from '@/store/treeEditorStore' import { TreeEditorLayout } from '@/components/tree-editor/TreeEditorLayout' import { ValidationSummary } from '@/components/tree-editor/ValidationSummary' @@ -15,6 +15,12 @@ import { cn, safeGetItem } from '@/lib/utils' import { toast } from '@/lib/toast' import { FlowAnalyticsPanel } from '@/components/analytics/FlowAnalyticsPanel' +/** Recursively check if any node in the tree has type 'answer' */ +function hasAnswerNodes(node: TreeStructure): boolean { + if (node.type === 'answer') return true + return (node.children || []).some(hasAnswerNodes) +} + export function TreeEditorPage() { const { id } = useParams<{ id: string }>() const navigate = useNavigate() @@ -292,6 +298,14 @@ export function TreeEditorPage() { return } + // Block publish if any answer placeholder nodes remain + const currentStructure = useTreeEditorStore.getState().treeStructure + if (currentStructure && hasAnswerNodes(currentStructure)) { + toast.error('Resolve all answer placeholders before publishing. Click each dashed stub card to assign a type.') + setSaving(false) + return + } + // Validate tree structure const errors = validate() const hasErrors = errors.some(e => e.severity === 'error')