feat: workflow graph system — blocks 1-20 complete checkpoint
Full graph-based workflow execution engine with: - WorkflowGraphRuntime with two-phase dispatch (collect → fire Celery tasks) - Node registry with contract validation, socket types, execution kinds - WorkflowRuntimeServices: preflight, context resolution, shadow-mode A/B - WorkflowRouter: CRUD + dispatch/preflight/run-history API endpoints - OutputTypeContracts: workflow binding, rollout-mode resolution - Admin router: output-type workflow binding endpoints - Frontend: complete workflow editor with drag-drop canvas, node inspector, module bundles, reference bundles, preflight panel, validation banner, authoring guidance, blueprint templates, shadow/rollout gate UI - Tests: comprehensive coverage for all workflow modules - Docs: NODE_CONTRACT_AUDIT and VALIDATION_ERROR_INVENTORY All 20 blocks from NEXT_20_BLOCK_BATCH_PLAN completed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -142,6 +142,44 @@ _THUMBNAIL_TASK_KEYS = {
|
||||
"transparent_bg",
|
||||
}
|
||||
|
||||
_RESOLVE_TEMPLATE_RUNTIME_KEYS = {
|
||||
"template_id_override",
|
||||
"material_library_path",
|
||||
"require_template",
|
||||
"disable_materials",
|
||||
"target_collection",
|
||||
"material_replace_mode",
|
||||
"lighting_only_mode",
|
||||
"shadow_catcher_mode",
|
||||
"camera_orbit_mode",
|
||||
}
|
||||
|
||||
_MATERIAL_MAP_RUNTIME_KEYS = {
|
||||
"material_override",
|
||||
"disable_materials",
|
||||
}
|
||||
|
||||
_AUTO_POPULATE_RUNTIME_KEYS = {
|
||||
"persist_updates",
|
||||
"refresh_material_source",
|
||||
"include_populated_products",
|
||||
}
|
||||
|
||||
_GLB_BBOX_RUNTIME_KEYS = {
|
||||
"glb_path",
|
||||
"source_preference",
|
||||
}
|
||||
|
||||
_OUTPUT_SAVE_RUNTIME_KEYS = {
|
||||
"expected_artifact_role",
|
||||
"require_upstream_artifact",
|
||||
}
|
||||
|
||||
_NOTIFY_RUNTIME_KEYS = {
|
||||
"channel",
|
||||
"require_armed_render",
|
||||
}
|
||||
|
||||
_AUTHORITATIVE_RENDER_SETTING_KEYS = {
|
||||
"render_engine",
|
||||
"engine",
|
||||
@@ -1135,16 +1173,25 @@ def _execute_glb_bbox(
|
||||
node_params: dict[str, Any],
|
||||
) -> tuple[dict[str, Any], str, str | None]:
|
||||
del node
|
||||
del session, workflow_context
|
||||
if state.setup is None or state.setup.cad_file is None:
|
||||
if state.setup is not None and state.setup.status == "skip":
|
||||
return _serialize_setup_result(state.setup), "skipped", state.setup.reason
|
||||
raise WorkflowGraphRuntimeError("glb_bbox requires a resolved cad_file")
|
||||
cad_file: CadFile | None = None
|
||||
glb_path = node_params.get("glb_path")
|
||||
|
||||
step_path = state.setup.cad_file.stored_path
|
||||
if state.setup is not None and state.setup.cad_file is not None:
|
||||
if state.setup.status == "skip":
|
||||
return _serialize_setup_result(state.setup), "skipped", state.setup.reason
|
||||
cad_file = state.setup.cad_file
|
||||
else:
|
||||
cad_file = _resolve_cad_file_context(session, workflow_context, state)
|
||||
|
||||
step_path = cad_file.stored_path
|
||||
glb_path = node_params.get("glb_path")
|
||||
source_preference = str(node_params.get("source_preference") or "auto")
|
||||
if glb_path is None and source_preference != "step_only" and state.setup.glb_reuse_path is not None:
|
||||
if (
|
||||
glb_path is None
|
||||
and source_preference != "step_only"
|
||||
and state.setup is not None
|
||||
and state.setup.glb_reuse_path is not None
|
||||
):
|
||||
glb_path = str(state.setup.glb_reuse_path)
|
||||
elif glb_path is None and source_preference != "step_only":
|
||||
step_file = Path(step_path)
|
||||
|
||||
Reference in New Issue
Block a user