Commit Graph
155 Commits
Author SHA1 Message Date
HartmutandClaude Sonnet 4.6 a11d2fb1e7 refactor: extract turntable branch and exhausted-retry handler from render_order_line_task
_render_turntable: Option B — resolved objects as params (render_invocation, step_path,
output_path, template, emit, pl). Session and PipelineLogger stay in the caller so
no second DB connection is opened and log steps roll up to the main task.

_handle_render_task_exhausted: extracted 68-line mark-as-failed block; retry/raise
logic with Celery self.retry stays in render_order_line_task since it needs the
bound-task context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 13:11:27 +02:00
HartmutandClaude Sonnet 4.6 e8b4580608 fix: workflow editor Phase 5/6 sign-off — save guard, conflict detection, dispatch pre-check
- Save button disabled for non-admins (canSave prop threaded through
  WorkflowEditor → WorkflowCanvas → WorkflowCanvasToolbar); tooltip
  explains why when hovered
- Optimistic concurrency: migration 072 adds updated_at to
  workflow_definitions; PUT /workflows/:id returns 409 when client sends
  a stale updated_at; frontend shows a specific reload-prompt toast
- _legacy_dispatch now routes through dispatch_order_line_render instead
  of calling render_order_line_task directly, so cancelled/rejected
  order lines are skipped before queueing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 11:39:02 +02:00
HartmutandClaude Sonnet 4.6 53b19f2ba1 fix: workflow blueprints freely editable after creation (preserve_user_graph)
canonicalize_workflow_config was silently rebuilding any workflow with
ui.blueprint or ui.preset == still_graph from the canonical template on
every save, preflight, and read — making blueprint-based workflows
effectively read-only.

Add preserve_user_graph=True flag that skips the rebuild blocks. Only
create_workflow still uses preserve_user_graph=False so blueprints are
correctly expanded at creation time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 11:17:32 +02:00
HartmutandClaude Sonnet 4.6 4946cc300a feat: editable branding — app name and subtitle configurable in Admin Settings
Adds app_name and app_subtitle as system settings with a dedicated
Branding tab in the Admin panel. Both values are served via a public
GET /api/admin/branding endpoint (no auth) so the login page can also
show the configured name before the user signs in.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 11:02:38 +02:00
HartmutandClaude Sonnet 4.6 c87857f836 feat: turntable + blend export smoke test coverage
- build_graph_turntable_config: accept render_params kwarg so smoke can
  use low settings (512x512, 24 frames) without touching golden case defaults
- add smoke naming + template functions for turntable and blend
- add ensure_workflow_turntable_smoke_resources() — provisions output type
  (mp4/turntable_video) + workflow graph, binds to
  Blender_Studio_Schadowcatcher_Anim template
- add ensure_workflow_blend_smoke_resources() — provisions output type
  (blend/blend_asset) + workflow graph, binds to BlenderStudio template
- add test_workflow_turntable_smoke() — preflight + dispatch + run tracking
- add test_workflow_blend_smoke() — preflight + dispatch + blend node check
- 6 new harness unit tests (17 total, all passing), using real asset:
  cad_file_id 8dd73335 (81113-l_cut.stp, has USD master + GLB)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 10:17:47 +02:00
HartmutandClaude Sonnet 4.6 44b52d05cc fix: cinematic output type guard + legacy_only migration
- Migration 070: seeds 'Cinematic Highlight' output type (legacy_only, no
  workflow link) for fresh installs
- Migration 071: patches existing cinematic output types — clears
  workflow_definition_id and forces legacy_only rollout mode. The row
  existed since 2026-03 with shadow mode + a linked workflow def;
  no BLENDER_CINEMATIC graph node exists so shadow execution would fail.
- API guard in output_types POST + PATCH: cinematic output types cannot
  receive a workflow_definition_id (HTTP 400)
- Defense-in-depth in dispatch_service: early legacy exit if
  render_settings.cinematic is true, regardless of rollout mode
- docs: learning erfasst — cinematic rollout mode footgun

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 10:04:07 +02:00
HartmutandClaude Sonnet 4.6 bb2b0f51b5 fix: cinematic render is_cinematic detection and usd_path str/Path handling
Three bugs causing all cinematic renders to silently fall through to the
turntable path and then immediately crash:

1. is_cinematic read from filtered invocation-override dict — 'cinematic' key
   is not in the allowed override key list for turntable_video, so it gets
   stripped. Fixed: read directly from output_type.render_settings.

2. render_turntable_to_file and render_cinematic_to_file both call
   usd_path.exists() but receive a str from the caller. Added the same
   isinstance str→Path conversion that render_still_to_file already had.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 22:32:16 +02:00
HartmutandClaude Sonnet 4.6 d2e4934cca 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>
2026-07-21 19:09:54 +02:00
HartmutandClaude Sonnet 4.6 c51dd8cd67 fix: guard persist_order_line_output against cancelled lines
Completed renders no longer overwrite a cancelled status — a Blender job
that finishes after a cancel is issued is now silently dropped instead of
flipping the line back to completed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 19:09:34 +02:00
HartmutandClaude Sonnet 4.6 84f40647b0 fix: resolve NameError masking cinematic render errors and fix frame count
- `render_cinematic_to_file` referenced undefined `stdout`/`stderr` in the
  Blender error path; replaced with `log_lines`/`stderr_lines` so the real
  Blender error is actually stored in render_log instead of a Python NameError
- Progress callback hardcoded 480 frames; now uses the `frame_count` variable
- Updated docstring to reflect actual 250 frames @ 25fps (not 480 @ 24fps)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 19:09:28 +02:00
Hartmut 98455ee579 Close workflow smoke template drift 2026-04-18 13:16:54 +02:00
Hartmut 3e810c74a3 chore: snapshot workflow migration progress 2026-04-12 11:49:04 +02:00
Hartmut 0cd02513d5 fix: normalize host runtime service endpoints 2026-04-09 19:47:17 +02:00
Hartmut e5c8ac7592 fix: align workflow material resolution with scene manifest 2026-04-09 19:41:13 +02:00
Hartmut dde04fcaa5 feat: unify order-line render invocation paths 2026-04-08 21:57:37 +02:00
Hartmut fe46dabfc5 feat: add workflow rollout gate signals 2026-04-08 21:44:02 +02:00
Hartmut 8c9648d5dc feat: make output types workflow-first contracts 2026-04-08 21:43:55 +02:00
Hartmut bd18cccb5e feat: harden workflow graph contracts 2026-04-08 21:32:14 +02:00
Hartmut 7e100ed334 feat: expose graph still workflow in editor 2026-04-08 11:16:47 +02:00
Hartmut ffcaef4659 feat: add workflow output comparison tooling 2026-04-07 11:45:28 +02:00
Hartmut f43f1e7420 feat: add duplicate-safe workflow shadow dispatch 2026-04-07 11:35:32 +02:00
Hartmut 26046fb2d6 feat: expose workflow execution modes in editor 2026-04-07 11:10:58 +02:00
Hartmut f9d4da52b9 feat: add graph workflow fallback and retry metadata 2026-04-07 10:56:45 +02:00
Hartmut c17b7d2e8f feat: execute workflow bridge nodes in graph runtime 2026-04-07 10:42:59 +02:00
Hartmut 6ad34ceed2 feat: add workflow run dispatch foundation 2026-04-07 10:11:46 +02:00
Hartmut ab1b220e79 test: close workflow phase 3 executor coverage 2026-04-07 10:00:38 +02:00
Hartmut 98b3eadcb2 feat: extract workflow notifications phase 3 2026-04-07 09:57:39 +02:00
Hartmut 160c198bb3 feat: extract workflow output save phase 3 2026-04-07 09:50:58 +02:00
Hartmut 9c93ecef49 feat: extract workflow bbox services phase 3 2026-04-07 09:42:06 +02:00
Hartmut 8f8d2e68b7 feat: extract workflow material services phase 3 2026-04-07 09:22:24 +02:00
Hartmut e3cda1c9f7 feat: extract workflow runtime phase 3 foundation 2026-04-07 09:09:40 +02:00
Hartmut 56ee5fc5bf feat: add workflow node registry phase 2 2026-04-07 08:59:27 +02:00
Hartmut 63e35ce807 feat: stabilize workflow phase 1 foundation 2026-04-07 08:48:48 +02:00
Hartmut 2a00abe91f fix: restore historical order visibility for HartOMat admins 2026-04-06 19:24:09 +02:00
Hartmut 448996b546 fix: stabilize HartOMat runtime startup 2026-04-06 13:10:51 +02:00
Hartmut b795f0e6d6 refactor: rebrand project to HartOMat 2026-04-06 12:45:47 +02:00
Hartmut fa7093307a chore: snapshot before HartOMat rebrand 2026-04-06 12:41:44 +02:00
HartmutandClaude Opus 4.6 feef2a0827 feat: AI searches product part materials — finds products WITH Durotect
Added product_material filter to find_product_renders:
- Searches cad_part_materials JSONB for materials assigned to CAD parts
- find_product_renders(transparent_only=true, product_material="Durotect")
  → finds 9 products that naturally have Durotect parts with transparent renders

Two material levels explained in system prompt rule 13:
- product_material: materials from STEP/Excel (Durotect_M, Stahl, Bronze)
- material_override: single material forced on ALL parts at render time

AI now searches product_material FIRST when user asks "with Durotect material"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:47:01 +01:00
HartmutandClaude Opus 4.6 9c6b210d51 fix: AI agent shows best available render when exact match not found
Rule 13: when searching with multiple criteria (transparent + Durotect),
decompose the search. Show what exists (1220 transparent renders) and
explain what's missing (no Durotect material applied). Never say
"no renders found" when transparent renders DO exist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:43:01 +01:00
HartmutandClaude Opus 4.6 54522a63d4 feat: render metadata from render_log for past renderings
find_product_renders now reads actual render metadata from the
render_log JSONB (stored at render time) via COALESCE fallback:
- engine: render_log.engine_used > render_log.engine > output_type setting
- width/height: render_log > output_type.render_settings
- samples: render_log > output_type.render_settings
- render_type: still/turntable/cinematic from render_log.type
- has_template: whether a .blend template was used

All past renderings now have correct metadata without re-processing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:35:19 +01:00
HartmutandClaude Opus 4.6 86921bacbd feat: render metadata in find_product_renders — material, format, resolution
find_product_renders now returns full render job metadata:
- material_override (effective: line override > output type override)
- output_format (with render_overrides applied)
- resolution (width x height)
- engine, samples
- order_number + order_id (for linking)
- is_animation flag

New material_override filter: search renders by material name
(e.g. transparent_only=true, material_override="Durotect" finds
renders with Durotect material on transparent background)

AI can now answer: "Show me a transparent Durotect render" by filtering
both transparency AND material in one query.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:24:02 +01:00
HartmutandClaude Opus 4.6 59f83f10ad fix: AI agent must confirm before ANY write action including overrides
Explicitly listed all write tools that require confirmation:
create_order, dispatch_renders, set_material_override, set_render_overrides

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:14:48 +01:00
HartmutandClaude Opus 4.6 8897afdebb fix: AI agent must confirm before creating orders or dispatching renders
Split rules into read-only vs write actions:
- READ (search, list, show images, status): execute immediately
- WRITE (create orders, dispatch, set overrides): ALWAYS ask for
  confirmation before executing

Prevents accidental render job creation from casual questions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:11:52 +01:00
HartmutandClaude Opus 4.6 20bcdee2a2 feat: AI agent links to products and orders in responses
System prompt rule 12: always format product mentions as
[ProductName](/products/UUID) and orders as [OrderNumber](/orders/UUID).

ReactMarkdown in ChatPanel already renders these as clickable links
with accent color styling, so users can navigate directly from chat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:07:44 +01:00
HartmutandClaude Opus 4.6 ef4c8eefc9 feat: AI agent knows material library — list_materials tool with alias search
Added list_materials tool to the chat agent:
- Searches SCHAEFFLER library materials by name, description, or alias
- Returns material name + schaeffler_code + aliases
- Enables: "zeig mir ein Bild mit Durotect-Material" → agent searches
  for "durotect" → finds SCHAEFFLER_020101_Durotect-Blue → uses as
  material_override

System prompt updated with rules 10-11:
- Explains alias → library material mapping
- Always use full SCHAEFFLER name for material_override

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:05:05 +01:00
HartmutandClaude Opus 4.6 c159bff2df fix: clean frames directory before cinematic/turntable re-render
Old frame PNGs from previous render attempts persisted in the frames
directory, causing FFmpeg to stitch the wrong number of frames.
Now rmtree's the directory before creating it fresh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:02:20 +01:00
HartmutandClaude Opus 4.6 458c6cd813 refactor: cinematic render — linear keyframes, 3 segments, 250 frames, white bg
Changes per user feedback:
- Keyframe interpolation: BEZIER → LINEAR (all fcurves set to LINEAR)
- Removed segment 4 (closeup) — now 3 segments only
- Frame count: 480 → 250 (10 seconds at 25fps)
- FPS: 24 → 25
- Easing removed — pure linear interpolation between segment params
- White background by default (World node Color = white)
- Transparent bg still available as override

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:57:42 +01:00
HartmutandClaude Opus 4.6 75ad397c09 fix: unbuffered stdout for live cinematic frame progress
Two fixes for frame progress not appearing in frontend:
1. Added flush=True to all print() calls in cinematic_render.py
2. Set PYTHONUNBUFFERED=1 in subprocess environment

Without these, Python buffers stdout inside Blender, so all frame
progress lines arrive in a batch after the process exits instead
of streaming line-by-line during rendering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:53:26 +01:00
HartmutandClaude Opus 4.6 e0714854d2 fix: stream Blender frame output to frontend for cinematic renders
The filter only matched [cinematic_render] tag but Blender outputs its
own "Saved: frame_NNNN.png" lines per frame. Now also matches "Saved:"
lines, extracts the frame number, and formats as:
  [cinematic_render] Frame 84/480 rendered

This shows live frame progress in the LiveRenderLog on the frontend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:42:36 +01:00
HartmutandClaude Opus 4.6 caffe7809c feat: live frame progress streaming for cinematic renders
Replaced communicate() (blocking) with selectors-based line-by-line
stdout streaming — same pattern as still render. Each frame now
streams live to the frontend:

  [cinematic_render] Frame 42/480 -- 55.3s elapsed (0.76 fps)

Pipeline: Blender stdout → log_callback → emit() → Redis →
LiveRenderLog poll (2s) → frontend display

Also added log_callback parameter to cinematic render task call.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:39:41 +01:00