Sub-ticket of epic #346. Depends on #347 (contracts + domain). Informed by the model-fit spike.
What: the GPU worker that executes pipeline stages by driving ProArt's per-model subprocess workers, replacing art_pipe's Flask/SQLite orchestrator with our RabbitMQ + Mongo orchestration. Scaffold with the add-event-handler-worker skill (project, appsettings, Dockerfile, infra stack file, Gitea CI workflow).
Scope:
SpikerSoft.EventHandlers.ArtPipeProcessor consuming art.asset.stage.requested; single-replica, pinned to the GPU host (infra template: spikersoft-embeddings/docker-stack-gpu.yml — node.hostname == SERVER, nvidia device reservation)
GpuCoordinator integration: request/renew/release VRAM lease per stage job using the model's vram_mb from its manifest (art_pipe/models/*/artpipe.json); queue while lease unavailable
Drive art_pipe backends via the worker protocol (art_pipe/src/artpipe/worker.py: stdin JSON → stdout NDJSON started|progress|result|error), per-model venvs preserved; map NDJSON progress events to art.asset.stage.progress messages and the stage workflow doc
Docker image: CUDA base, art_pipe checkout + bootstrapped model venvs + HF weight cache volume; document image size / volume strategy (weights are tens of GB — volume-mount, don't bake)
Modeling stage end-to-end first: image→3D (TRELLIS — parity with today's SpikerSoft.EventHandlers.Trellis3D.Python) and text→3D (per spike outcome, e.g. Hunyuan3D-2 or TripoSR), then decimation + mesh-health gate, GLB artifact → GridFS
Stage completion publishes art.asset.stage.completed with artifact refs; failure → terminal error state on the workflow doc (no partial artifacts exposed), retry honors RestartFromStageCommand
Serilog→Seq + OTLP tracing with correlation from the originating command (telemetry-correlation rule); AOT-viability per repo skill where applicable
Decommission plan for SpikerSoft.EventHandlers.Trellis3D.Python once parity is proven (its .gitea/workflows/spikersoft-trellis3d.yml CI too)
Note: art_pipe assumes nvidia-smi/CUDA at startup (main.py::_check_gpu_compat) — the worker container must pass the GPU through. Keep the .NET consumer thin: process supervision + protocol translation only; no model code in .NET.
Acceptance: submitting an asset from P1 produces a real GLB in GridFS via a VRAM-leased art_pipe subprocess on the GPU host, with stage progress visible in the workflow doc and traces in Jaeger/Seq; a second concurrent submission queues on the lease rather than OOMing the card.
Sub-ticket of epic #346. Depends on #347 (contracts + domain). Informed by the model-fit spike.
**What:** the GPU worker that executes pipeline stages by driving ProArt's per-model subprocess workers, replacing art_pipe's Flask/SQLite orchestrator with our RabbitMQ + Mongo orchestration. Scaffold with the `add-event-handler-worker` skill (project, appsettings, Dockerfile, infra stack file, Gitea CI workflow).
**Scope:**
- [ ] `SpikerSoft.EventHandlers.ArtPipeProcessor` consuming `art.asset.stage.requested`; single-replica, pinned to the GPU host (infra template: `spikersoft-embeddings/docker-stack-gpu.yml` — `node.hostname == SERVER`, nvidia device reservation)
- [ ] GpuCoordinator integration: request/renew/release VRAM lease per stage job using the model's `vram_mb` from its manifest (`art_pipe/models/*/artpipe.json`); queue while lease unavailable
- [ ] Drive art_pipe backends via the worker protocol (`art_pipe/src/artpipe/worker.py`: stdin JSON → stdout NDJSON `started|progress|result|error`), per-model venvs preserved; map NDJSON progress events to `art.asset.stage.progress` messages and the stage workflow doc
- [ ] Docker image: CUDA base, art_pipe checkout + bootstrapped model venvs + HF weight cache volume; document image size / volume strategy (weights are tens of GB — volume-mount, don't bake)
- [ ] Modeling stage end-to-end first: image→3D (TRELLIS — parity with today's `SpikerSoft.EventHandlers.Trellis3D.Python`) and text→3D (per spike outcome, e.g. Hunyuan3D-2 or TripoSR), then decimation + mesh-health gate, GLB artifact → GridFS
- [ ] Stage completion publishes `art.asset.stage.completed` with artifact refs; failure → terminal error state on the workflow doc (no partial artifacts exposed), retry honors `RestartFromStageCommand`
- [ ] Serilog→Seq + OTLP tracing with correlation from the originating command (telemetry-correlation rule); AOT-viability per repo skill where applicable
- [ ] Decommission plan for `SpikerSoft.EventHandlers.Trellis3D.Python` once parity is proven (its `.gitea/workflows/spikersoft-trellis3d.yml` CI too)
**Note:** art_pipe assumes `nvidia-smi`/CUDA at startup (`main.py::_check_gpu_compat`) — the worker container must pass the GPU through. Keep the .NET consumer thin: process supervision + protocol translation only; no model code in .NET.
**Acceptance:** submitting an asset from P1 produces a real GLB in GridFS via a VRAM-leased art_pipe subprocess on the GPU host, with stage progress visible in the workflow doc and traces in Jaeger/Seq; a second concurrent submission queues on the lease rather than OOMing the card.
Requirement added by the Mac workstream (#359): Docker on macOS has no GPU/MPS passthrough, so this worker will run containerized on Linux (CUDA) but as a native host process on macOS (MPS). Keep it host-agnostic:
art_pipe checkout path, per-model venv locations, and Blender binary path come from config, not baked Dockerfile paths
model/profile selection is config-driven (linux-cuda vs macos-mps profile, see #357)
GpuCoordinator lease client must be toggleable (bypass flag for single-user dev machines, #359)
None of this changes the Linux deployment; it just means no /app/... absolute-path assumptions in the .NET consumer.
Requirement added by the Mac workstream (#359): Docker on macOS has no GPU/MPS passthrough, so this worker will run **containerized on Linux (CUDA)** but as a **native host process on macOS (MPS)**. Keep it host-agnostic:
- art_pipe checkout path, per-model venv locations, and Blender binary path come from config, not baked Dockerfile paths
- model/profile selection is config-driven (linux-cuda vs macos-mps profile, see #357)
- GpuCoordinator lease client must be toggleable (bypass flag for single-user dev machines, #359)
None of this changes the Linux deployment; it just means no `/app/...` absolute-path assumptions in the .NET consumer.
Topology refinement (see epic comment): one codebase, N swarm services.
ArtPipe:Stages config selects which stage routing keys this instance consumes (e.g. ["modeling"]); queue-per-stage on the art.asset.lifecycle exchange so services don't compete for each other's work
This ticket ships the image + the first service: artpipe-modeling as a new stack file in spikersoft-infrastructure (template: spikersoft-embeddings/docker-stack-gpu.yml — nvidia device reservation, node.hostname == SERVER, registry git.spikersoft.com/spikerj/..., Gitea CI workflow per add-event-handler-worker)
#349 adds artpipe-imaging (concept + texturing), #350 adds artpipe-rigging (rig + animate + export) — same image, different ArtPipe:Stages env, own stack files, each holding its own GpuCoordinator leases
All API↔worker communication stays RabbitMQ-only (no HTTP between .NET API and GPU services); results/progress flow back as events the API side projects into Mongo + SignalR
Mac dev mode (#359): same binary, native process, all stages in one consumer, lease client bypassed
Model venvs/weights stay on volumes so the shared image doesn't balloon; each service only bootstraps the venvs its stage set needs (manifest-driven).
Topology refinement (see epic comment): **one codebase, N swarm services**.
- `ArtPipe:Stages` config selects which stage routing keys this instance consumes (e.g. `["modeling"]`); queue-per-stage on the `art.asset.lifecycle` exchange so services don't compete for each other's work
- This ticket ships the image + the **first** service: `artpipe-modeling` as a new stack file in `spikersoft-infrastructure` (template: `spikersoft-embeddings/docker-stack-gpu.yml` — nvidia device reservation, `node.hostname == SERVER`, registry `git.spikersoft.com/spikerj/...`, Gitea CI workflow per `add-event-handler-worker`)
- #349 adds `artpipe-imaging` (concept + texturing), #350 adds `artpipe-rigging` (rig + animate + export) — same image, different `ArtPipe:Stages` env, own stack files, each holding its own GpuCoordinator leases
- All API↔worker communication stays RabbitMQ-only (no HTTP between .NET API and GPU services); results/progress flow back as events the API side projects into Mongo + SignalR
- Mac dev mode (#359): same binary, native process, all stages in one consumer, lease client bypassed
Model venvs/weights stay on volumes so the shared image doesn't balloon; each service only bootstraps the venvs its stage set needs (manifest-driven).
.NET side complete and up for merge: backend PR #62 + infra PR spikersoft-infrastructure#5 (artpipe-modeling GPU stack). 131/131 unit tests locally (27 new: orchestrator advancement/failure/cancellation, progress throttle, config binding). Notable: routing keys are now stage-suffixed (art.asset.stage.requested.<stage>, queue per stage) — API unchanged since RemoteDispatchBehavior reads the command's RoutingKey; GpuCoordinator integration uses the existing IGpuLeaseService/WithGpuScheduling() contract, ArtPipe:BypassGpuLease for Mac dev.
Ticket stays open for the acceptance run (real GLB via VRAM-leased art_pipe subprocess on the GPU host): needs model venvs bootstrapped on SERVER + the art_pipe checkout at the volume path in the stack header. ArtPipe:UseFakeExecutor=true provides a venv-less dev loop meanwhile. #357's Mac validation will exercise the same subprocess driver natively first.
.NET side complete and up for merge: backend PR [#62](https://git.spikersoft.com/spikerj/spikersoft-backend/pulls/62) + infra PR [spikersoft-infrastructure#5](https://git.spikersoft.com/spikerj/spikersoft-infrastructure/pulls/5) (`artpipe-modeling` GPU stack). 131/131 unit tests locally (27 new: orchestrator advancement/failure/cancellation, progress throttle, config binding). Notable: routing keys are now stage-suffixed (`art.asset.stage.requested.<stage>`, queue per stage) — API unchanged since `RemoteDispatchBehavior` reads the command's RoutingKey; GpuCoordinator integration uses the existing `IGpuLeaseService`/`WithGpuScheduling()` contract, `ArtPipe:BypassGpuLease` for Mac dev.
Ticket stays open for the acceptance run (real GLB via VRAM-leased art_pipe subprocess on the GPU host): needs model venvs bootstrapped on SERVER + the art_pipe checkout at the volume path in the stack header. `ArtPipe:UseFakeExecutor=true` provides a venv-less dev loop meanwhile. #357's Mac validation will exercise the same subprocess driver natively first.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Sub-ticket of epic #346. Depends on #347 (contracts + domain). Informed by the model-fit spike.
What: the GPU worker that executes pipeline stages by driving ProArt's per-model subprocess workers, replacing art_pipe's Flask/SQLite orchestrator with our RabbitMQ + Mongo orchestration. Scaffold with the
add-event-handler-workerskill (project, appsettings, Dockerfile, infra stack file, Gitea CI workflow).Scope:
SpikerSoft.EventHandlers.ArtPipeProcessorconsumingart.asset.stage.requested; single-replica, pinned to the GPU host (infra template:spikersoft-embeddings/docker-stack-gpu.yml—node.hostname == SERVER, nvidia device reservation)vram_mbfrom its manifest (art_pipe/models/*/artpipe.json); queue while lease unavailableart_pipe/src/artpipe/worker.py: stdin JSON → stdout NDJSONstarted|progress|result|error), per-model venvs preserved; map NDJSON progress events toart.asset.stage.progressmessages and the stage workflow docSpikerSoft.EventHandlers.Trellis3D.Python) and text→3D (per spike outcome, e.g. Hunyuan3D-2 or TripoSR), then decimation + mesh-health gate, GLB artifact → GridFSart.asset.stage.completedwith artifact refs; failure → terminal error state on the workflow doc (no partial artifacts exposed), retry honorsRestartFromStageCommandSpikerSoft.EventHandlers.Trellis3D.Pythononce parity is proven (its.gitea/workflows/spikersoft-trellis3d.ymlCI too)Note: art_pipe assumes
nvidia-smi/CUDA at startup (main.py::_check_gpu_compat) — the worker container must pass the GPU through. Keep the .NET consumer thin: process supervision + protocol translation only; no model code in .NET.Acceptance: submitting an asset from P1 produces a real GLB in GridFS via a VRAM-leased art_pipe subprocess on the GPU host, with stage progress visible in the workflow doc and traces in Jaeger/Seq; a second concurrent submission queues on the lease rather than OOMing the card.
Requirement added by the Mac workstream (#359): Docker on macOS has no GPU/MPS passthrough, so this worker will run containerized on Linux (CUDA) but as a native host process on macOS (MPS). Keep it host-agnostic:
None of this changes the Linux deployment; it just means no
/app/...absolute-path assumptions in the .NET consumer.Topology refinement (see epic comment): one codebase, N swarm services.
ArtPipe:Stagesconfig selects which stage routing keys this instance consumes (e.g.["modeling"]); queue-per-stage on theart.asset.lifecycleexchange so services don't compete for each other's workartpipe-modelingas a new stack file inspikersoft-infrastructure(template:spikersoft-embeddings/docker-stack-gpu.yml— nvidia device reservation,node.hostname == SERVER, registrygit.spikersoft.com/spikerj/..., Gitea CI workflow peradd-event-handler-worker)artpipe-imaging(concept + texturing), #350 addsartpipe-rigging(rig + animate + export) — same image, differentArtPipe:Stagesenv, own stack files, each holding its own GpuCoordinator leasesModel venvs/weights stay on volumes so the shared image doesn't balloon; each service only bootstraps the venvs its stage set needs (manifest-driven).
.NET side complete and up for merge: backend PR #62 + infra PR spikersoft-infrastructure#5 (
artpipe-modelingGPU stack). 131/131 unit tests locally (27 new: orchestrator advancement/failure/cancellation, progress throttle, config binding). Notable: routing keys are now stage-suffixed (art.asset.stage.requested.<stage>, queue per stage) — API unchanged sinceRemoteDispatchBehaviorreads the command's RoutingKey; GpuCoordinator integration uses the existingIGpuLeaseService/WithGpuScheduling()contract,ArtPipe:BypassGpuLeasefor Mac dev.Ticket stays open for the acceptance run (real GLB via VRAM-leased art_pipe subprocess on the GPU host): needs model venvs bootstrapped on SERVER + the art_pipe checkout at the volume path in the stack header.
ArtPipe:UseFakeExecutor=trueprovides a venv-less dev loop meanwhile. #357's Mac validation will exercise the same subprocess driver natively first.Board-sweep verified complete: backend PR #62 (ArtPipeProcessor stage consumer + subprocess driver + VRAM lease) + infra PRs #5/#6 (modeling GPU stack) merged; SpikerSoft.EventHandlers.ArtPipeProcessor/ and infra spikersoft-artpipe-modeling/ verified in the trees. Closing.