The analysis
ComfyUI substrate inventory
Read at: magieva-core branch fix/residency-fail-closed-round-lesson, commit ef3798123c5 (2026-10-27). All line numbers are against that commit.
Headline finding. Magieva has a genuinely shipped ComfyUI substrate, not a plan: a complete Local Resource Manager (LRM) connector that speaks ComfyUI's real HTTP API, five embedded workflow graphs (four registered), GCE GPU provisioning that installs ComfyUI from scratch and registers it back into LRM, a task-executor video provider, a weight-licence hosting gate with per-model pins, and a desktop Electron install/run path. But it is fragmented into three parallel invocation paths that do not share a gate, and several seams that look wired are dead: internal/psdedit/local.go POSTs to an LRM route that does not exist, the contentstudio COMFYUI_API_URL façade is set by nothing in any deployment config, the comfyui_lrm transport has no registered Go driver, and the desktop's ComfyUI registration is opt-in and defaults off. The planning docs are stale in both directions — docs/planning/26.35/os-video-model-integration/README.md:3 still says "Planning. Nothing built." while its own Phase 1 is live in production, and docs/planning/26.35/status/M3.md says "No ComfyUI workflow graphs for video" while four such graphs now exist and two are verified by execution on real GPUs.
What is actually shipped
Status key: (a) live/wired · (b) exists but behind a flag / env var / unshipped · (c) planned only.
| Capability | Entry point (path:line) | What it does | Evidence it is live |
|---|---|---|---|
| ComfyUI connector (LRM) | services/local-resource-manager/connector_comfyui.go:25 | Full Connector + GenerationConnector + GPUInfoProvider: health, model list, workflow submit, poll, output extraction, image upload | Registered in factory connector.go:195-196; compile-time assertions connector_comfyui.go:917-919; tests connector_comfyui_test.go, connector_generation_test.go, comfyui_video_capability_test.go, comfyui_video_output_test.go |
| Workflow template store | services/local-resource-manager/comfyui_workflows.go:22-23, :51-93 | //go:embed comfyui_workflows/*.json; maps (capability × model) → graph file. Model-keyed so one model's graph is never served for another's | lookupWorkflowTemplate :98; comfyui_workflows_test.go |
| Param injection | services/local-resource-manager/comfyui_workflow_params.go | Graph-agnostic injection of prompt/negative/seed/dimensions/frame-count/checkpoint, matching on class_type + graph links, never node ids | findPromptNodes :91; setLoadImageFilename comfyui_workflows.go:190; comfyui_workflows_test.go |
| LRM HTTP API | services/local-resource-manager/main.go:320-371 | /v1/generate, /v1/generate/async, /v1/generate/jobs/:id, /v1/images/generations, /v1/chat/completions, /api/v1/local/backends, /api/v1/local/models, /api/v1/local/eligibility/:orgId | Route registrations in main.go; declared in endpoints.go:22-44 for AEIOUY |
| GPU runner provisioning | services/gpu-runner-service/provisioner.go, provisioner_gce.go, startup_script.sh | Creates a GCE VM, runs startup_script.sh (NVIDIA driver → ComfyUI clone → venv → torch cu128 → node packs → weights staging → launch on 0.0.0.0:8188), polls /system_stats, registers with LRM as origin=platform_gpu | manager.go awaitReadyAndRegister; startup_script_test.go (boot-path invariants incl. the 1038lab RMBG fix); lrm_client.go:61 |
| Capability → GPU tier routing | services/gpu-runner-service/provisioner.go:96-103 | defaultTierForCapability returns rtx6000 for everything (was text-to-video → h100-mega) | provisioner.go:137-160 resolveTier precedence override → Bernini → registry → capability |
| Per-model tier from registry | services/gpu-runner-service/catalog.go:89 | tierForModel reads ai_model_execution_tiers.gpu_tier_key / gpu_tier_fallback_key (read-only Integrations pool) | catalog_test.go; verified live in ws-18 by mutating the row (M3.md "Follow-up: the catalog readers") |
| ComfyUI video provider | internal/task-executor/providers/video/comfyui.go:41 | SupportsModel("comfyui/…"), picks capability from ImageURL presence, submits to LRM async, polls, downloads | Registered unconditionally registry.go:61-63; lrm_client.go shared plumbing |
| AIMRS local execution | internal/aimrs/local_exec.go:248 (ExecuteLocalGeneration), :341 (ExecuteLocalImage) | POSTs to {resolved.EndpointURL}/generate and /images/generations; Capability is the ComfyUI workflow selector | Callers internal/task-executor/archetypes/river_artistic.go:2735, :2808, :2901 |
| River local media paths | river_artistic.go:2901 (tryLocalImage), :2808 (tryLocalVideo), :2735 (tryLocalImageVariation) | Resolve via AIMRS; if IsLocal(), generate at Cost: 0 with route_type=local_device metadata; fall through to cloud on any miss | fallbackLocalImageCheckpoint :2585 = flux1-schnell; defaultLocalVideoCheckpoint = ltx-video |
| Weight-licence hosting gate | internal/modellicense/validate.go:31 | ValidatePlatformHosting → HostedAllowed/RequiresAgreement/Prohibited/Unknown; fail-closed | Enforced at services/gpu-runner-service/manager.go (Provision) and services/local-resource-manager/backend_handler.go:224 |
| $0 pricing for ComfyUI | internal/intelligence/sync/pricing/runner.go:250 | localFreeProviders allowlist includes comfyui | Explicit allowlist, "never a heuristic" |
| Local-provider billing bypass | internal/contentstudio/compute_operations.go:53 | isLocalProvider returns true for comfyui | — |
| Desktop ComfyUI install/run | web/electron/main/backends/NativeProcessOrchestrator.ts:361, web/scripts/setup-comfyui.sh | Clones ComfyUI, creates venv, installs ComfyUI-LTXVideo + ComfyUI-RMBG, writes launcher on port 8188 | runComfyUISetup :1056; port-ownership refusal :505 |
| Desktop backend install API | api/operations/desktop_install_backend.go:93 | supportedBackends = {"ollama": true, "comfyui": true} | Validated backend-type guard |
| Catalog seeds | infra/supabase/migrations/20260630000100_INTEGRATIONS_comfyui_image_models.sql, 20260831130000, 20260831130100, 20260831130200 | comfyui provider row; FLUX/SDXL/SD3.5/LTX-Video image models; 7 canonical video models + 7 comfyui_lrm bindings + 9 adapters; per-model tier rows | M3.md: "catalog AND first-frame work are live in PRODUCTION on 26.35.5" |
(b) Exists but behind a flag / env var / unshipped
| Thing | Where | Gate | |||||
|---|---|---|---|---|---|---|---|
| Desktop ComfyUI auto-registration | web/electron/main/startup.ts:1535-1536 | localProcessing.image.enabled, default false — "Opt-in … because ComfyUI is heavy" | |||||
| GPU auto-provision on demand | generation_proxy_handler.go:317 | GPU_RUNNER_AUTOPROVISION (default "true"), video modality only | |||||
| Weight mirroring to GCS | startup_script.sh:135-157 | GPU_RUNNER_WEIGHTS_BUCKET unset everywhere → staging skipped, "shipped inert" (M3.md) | |||||
| Platform GPU in production | — | M3.md: prod sets no GPU_RUNNER_* (provisioner is dryrun) and has 0 rows in local_backends, while all 7 comfyui/* models are is_available=t → a prod user gets a 20s retry loop then failure. "Deployed ≠ renders." | |||||
contentstudio ComfyUI render façade | internal/contentstudio/character_render_controlnet.go:175 | COMFYUI_API_URL is referenced only in code + planning docs; set in no helm value, compose file, or env. No services/comfyui-service exists in the repo (only named in docs/planning/26.28/atlas-2d3d-character-pipeline/README.md:138) | |||||
comfyui_lrm transport driver | internal/modelparams/transport.go:186 | RegisterDriver is never called outside tests; Transport("comfyui_lrm").Valid() is false → Layer-1 coercion only, Layer-2 rendering withheld (schema_params.go:82-101) | |||||
first_last_frame_to_video_wan22_a14b.json | comfyui_workflows.go:82-92 | Present and GPU-verified but deliberately unregistered: GenerationRequest carries one input image and setLoadImageFilename binds it to every LoadImage node; this graph has two | |||||
internal/psdedit/local.go | internal/psdedit/local.go:72 | POSTs to {baseURL}/api/v1/local/generate — no such LRM route exists (main.go has /v1/generate and `/api/v1/local/backends | models | policies | usage | eligibility | nodes). Also sends image_base64, but LRM's GenerationRequest.InputImageData is json:"-" (generation_types.go:51) so it would be dropped. Capability strings are image_to_image/upscale/inpaint (underscores) vs the store's image-to-image (hyphen); no upscale or inpaint template exists at all. Wired only when LOCAL_RESOURCE_MANAGER_URL is set (env.go:52`) |
The ComfyUI integration contract
LRM → ComfyUI (the real protocol)
All in services/local-resource-manager/connector_comfyui.go. HTTP only — there is no websocket client anywhere in LRM (grep for websocket in services/local-resource-manager/*.go returns only the unrelated relay connector for desktop Ollama, connector_relay.go:1). Progress is polled.
| Purpose | Call | Line |
|---|---|---|
| Health | GET {base}/system_stats → ComfyUISystemStats{Devices[]} | :45-46 |
| List checkpoints | GET {base}/object_info/CheckpointLoaderSimple, reads input.required.ckpt_name[0][] | :73-74 |
| Weight reconciliation | GET {base}/object_info (all nodes) | :632 |
| Upload input image | POST {base}/upload/image (multipart) → returns filename | :681-700 |
| Submit graph | POST {base}/prompt body {"prompt": <graph>, "client_id": <uuid>} → {"prompt_id","number"} | :261-295 |
| Poll | GET {base}/history/{prompt_id} → map[promptID]ComfyUIHistoryEntry; absent ⇒ processing | :299-331 |
| Error detect | entry.status.status_str == "error" | :334 |
| Output URL | GET {base}/view?filename=…&subfolder=…&type=… | :442 |
| GPU info | via /system_stats devices | :490 |
Output extraction is a documented trap. comfyOutputKeys = ["videos","gifs","audio","images"] (:379) — core SaveVideo emits the mp4 under images, not videos; the comment records this was corrected against a live ComfyUI (frontend 1.49.6) on 2026-08-26. MIME is derived from extension (comfyMimeByExt, :384), because the old code hardcoded image/png for everything.
Fail-loud guards (both are the fix for a real silent-wrong-output defect):
req.Control != nil→ hard error"control conditioning … is not implemented"(:220-231). Control graphs are Phase 4.3.- A non-image capability with no template → hard error naming capability and model (
:238-255), instead of the txt2img fallback that once answered a video request with a PNG.
Callers → LRM
| Caller | Endpoint | Payload |
|---|---|---|
internal/aimrs/local_exec.go:296 (ExecuteLocalGeneration) | POST {EndpointURL}/generate | {modality, capability, model, prompt, negative_prompt, width, height, duration, fps, input_image_url, strength, num_outputs, control} |
internal/aimrs/local_exec.go:383 (ExecuteLocalImage) | POST {EndpointURL}/images/generations | OpenAI-shaped {prompt, model, n, size, negative_prompt, seed, steps, cfg_scale} |
internal/task-executor/providers/video/comfyui.go:277 | POST {LRM}/v1/generate/async | {organization_id, modality:"video", capability, model, prompt, width, height, fps, duration, input_image_url?} |
| …then polls | GET {LRM}/v1/generate/jobs/{id}?backend_id=… | {status, progress, outputs[{url,mime_type}], error} |
EndpointURL is lrmClient.baseURL + "/v1" (services/aimrs-service/handlers.go:166), so ExecuteLocalGeneration lands on LRM's synchronous /v1/generate.
⚠️ The three invocation paths do not share a billing gate — this is load-bearing
HandleUniversalGeneration (sync, /v1/generate) refuses platform-GPU generation for any provider that is not Bernini:
// generation_proxy_handler.go:239-249
if backend.Origin == OriginPlatformGPU {
if h.billing == nil { … "platform GPU billing not configured" }
if backend.ProviderName != ProviderBernini {
return 503 {"error":"no flat pricing configured for this platform model","code":"NO_PRICING"}
}
HandleAsyncGeneration (/v1/generate/async, :344-396) has no billing gate and no provider check — it goes straight to genConn.GenerateAsync.
HandleImageGeneration (/v1/images/generations, :59-181) also has no billing gate and no provider check — it goes straight to genConn.Generate at :140.
So of the three ComfyUI invocation paths, only one gates:
| Path | Route | Platform-GPU ComfyUI |
|---|---|---|
river_artistic.tryLocalImage → ExecuteLocalImage | POST /v1/images/generations | works, unbilled (no gate) |
| task-executor video provider | POST /v1/generate/async | works, unbilled (no gate) |
river_artistic.tryLocalVideo / tryLocalImageVariation → ExecuteLocalGeneration | POST /v1/generate | 503 NO_PRICING (Bernini-only gate) |
The consequence is inverted from what one would expect: the two paths that do work on a platform GPU are the two with no billing gate, and the one path that is correctly gated is the one that cannot serve ComfyUI at all. aimrs.ExecuteLocalGeneration is therefore usable for ComfyUI only on origin=customer_device.
GPU runner → LRM registration
services/gpu-runner-service/lrm_client.go:70-83 POSTs to /api/v1/local/backends:
{"organization_id":"…","provider_name":"comfyui","display_name":"platform-gpu rtx6000 (comfyui/wan2.2-ti2v-5b)",
"base_url":"http://<ip>:8188","backend_type":"image","capabilities":["<one capability>"],
"origin":"platform_gpu","max_concurrent":4,
"hosted_models":[{"model_id":"comfyui/wan2.2-ti2v-5b","license":"apache-2.0"}]}
Note backend_type is "image" for ComfyUI and "video" only for Bernini (:66-69) — a ComfyUI runner is registered as an image backend even when it was provisioned for a video capability. hosted_models deliberately carries no clearance field: LRM re-reads org_license_acceptances itself (lrm_client.go:34-44), so the two gates judge the same fact independently.
Shipped workflow graphs
Five files in services/local-resource-manager/comfyui_workflows/; four registered.
| File | Registered key | Nodes / models | What it does | Verification |
|---|---|---|---|---|
background_removal.json | {background-removal} (model-agnostic) | LoadImage → RMBG → SaveImage | Bria RMBG-2.0 background removal; the graph names its own weights | The only template that existed pre-26.35 |
text_to_video_wan22.json | {text-to-video, wan2.2-ti2v-5b} | UNETLoader wan2.2_ti2v_5B_fp16.safetensors; CLIPLoader umt5_xxl_fp8_e4m3fn_scaled.safetensors; VAELoader wan2.2_vae.safetensors; Wan22ImageToVideoLatent; KSampler; ModelSamplingSD3; CreateVideo; SaveVideo | Wan 2.2 TI2V-5B text-to-video | VERIFIED on real GPU 2026-08-26: 121 frames @ 832×480, h264. ComfyUI's own video_wan2_2_5B_ti2v.json exported to API format. Re-confirmed staging 2026-08-27 |
image_to_video_wan22_ti2v.json | {image-to-video, wan2.2-ti2v-5b} | Same as above plus restored LoadImage (node 56) | Wan 2.2 TI2V-5B image-to-video | VERIFIED 2026-08-28: 832×480, 121 frames, 255 s. Conditioning checked, not just completion — frame 0 mean|diff| 1.41 vs uploaded image, rising to 163 by frame 120 |
image_to_video_wan22_a14b.json | {image-to-video, wan2.2-i2v-a14b} | UNETLoader ×2 (wan2.2_i2v_high_noise_14B_fp8_scaled, …low_noise_14B_fp8_scaled); CLIPLoader umt5_xxl…; VAELoader wan_2.1_vae; WanImageToVideo; KSamplerAdvanced ×2; CreateVideo; SaveVideo | Wan 2.2 I2V-A14B MoE pair — the case that forced (capability × model) keying | VERIFIED 2026-08-28: 640×640, 81 frames, 1254 s, peak 21737/23034 MiB on an L4. DERIVED, not exported — upstream is a subgraph routed through lightx2v LoRAs we do not stage |
first_last_frame_to_video_wan22_a14b.json | NOT REGISTERED | WanFirstLastFrameToVideo; UNETLoader ×2; LoadImage ×2 (nodes 80, 89); KSamplerAdvanced ×2 | Wan 2.2 I2V-A14B first/last-frame-to-video | VERIFIED 2026-08-28 (L4, 640×640, 81 frames, 20 min 58 s, peak 21151/23034 MiB) but deliberately unwired — see (b) above |
Models with NO graph (registered in the catalog and offered in the picker, but a request fails loudly): wan2.2-t2v-a14b, ltx-2.3, ltx-2.5, scail-2, ltx-video. This is the honest fail-loud path, not a silent fallback — but it means the customer-facing model list (customer-docs/site-src/reference/models/comfyui--local.md:10-23) advertises models that cannot render.
Models and licences
The gate
internal/modellicense/ classifies weight licences for platform-GPU hosting, deliberately separate from BORG's SPDX code-licence check (policy.go:1-15): "a model's node-pack/code can be MIT while its downloadable weights carry a restrictive license." The canonical example given is Bria RMBG-2.0 — ComfyUI-RMBG node code permissive, RMBG-2.0 weights requiring a commercial agreement.
ValidatePlatformHosting(modelID, license, hasClearance) (validate.go:31): HostedAllowed → nil · RequiresAgreement → nil only if clearance · Prohibited → always error · Unknown → error (fail closed).
Enforced independently at both hosting paths: gpu-runner-service/manager.go (Provision, before creating the VM) and local-resource-manager/backend_handler.go:224 (on origin=platform_gpu registration). Both read clearance from org_license_acceptances, never from the request body (backend_handler.go:193, lrm_client.go:34-44).
Model → licence map
Pins in internal/modellicense/policy.go (knownWeightLicense, :41-80), asserted by internal/modellicense/os_video_models_test.go:22-47:
| Model id | Licence | Disposition |
|---|---|---|
comfyui/wan2.2-ti2v-5b, comfyui/wan2.2-t2v-a14b, comfyui/wan2.2-i2v-a14b | apache-2.0 | HostedAllowed |
comfyui/scail-2 | mit | HostedAllowed |
comfyui/ltx-2.3, comfyui/ltx-2.5, Lightricks/LTX-2-19b-IC-LoRA-* | ltx-2.x-community | RequiresAgreement — fails closed |
comfyui/ltx-video (0.9.x) | unpinned (LTXV Open Weights) | Unknown — fails closed (os_video_models_test.go:140-148) |
rmbg-2.0, rmbg-1.4, briaai/rmbg, bria | bria-rmbg | RequiresAgreement |
bernini, wan2.2, wan-2.2, qwen2.5-vl | apache-2.0 | HostedAllowed |
Two subtleties worth carrying into any reuse:
WeightLicenseForpicks the most restrictive match, not the first (policy.go:202-218) — the comment records this replaced a map-iteration-order fail-OPEN coin flip on a gate deciding commercial hosting rights.- Adapters classify independently of their base (
os_video_models_test.go:106-134): every LTX IC-LoRA is restrictive even on an Apache-2.0 Wan base, soValidatePlatformHostingruns per adapter.manager.gostates the base passing the gate "does NOT clear its adapters." - Customer-device hosting is deliberately NOT gated (
policy.go:70-74): "that is the customer's own use, and the asymmetry is correct, not a bug to fix."
Desktop / local install path
Install — web/scripts/setup-comfyui.sh (166 lines), invoked by NativeProcessOrchestrator.runComfyUISetup (:1056), which locates the script at Resources/scripts/setup-comfyui.sh (packaged) or ../../../scripts/setup-comfyui.sh (dev). It checks Python ≥3.10, creates a venv at ~/.magieva/comfyui-data/venv, clones ComfyUI, installs requirements.txt, installs two custom-node packs, and writes a launcher at ~/.magieva/bin/comfyui/comfyui_launcher that runs main.py --listen 0.0.0.0 --port 8188 --enable-cors-header.
Run — backend definition at NativeProcessOrchestrator.ts:361-378: binaryName: 'comfyui_launcher', processName: 'magieva-comfyui', hostPort: 8188, healthProbePath: '/system_stats', capabilities ['text-to-image','text-to-video','image-to-image','background-removal'] (hyphenated to match LRM's canonical vocabulary). Port ownership is checked before spawn (:505, refuses with pair_owns_port).
Announce — startup.ts:1535 registerComfyUINode, gated on localProcessing.image.enabled (default false), calls install({backend_type:'comfyui', expose_via:'cloudflared'}) then bridge.sendBackendReady({backendType:'comfyui', capabilities, maxConcurrent: 1}). The desktop does not POST to LRM directly — it goes through the event-bridge (docs/planning/26.27/local-magieva/03-local-media-routing-comfyui-aimrs.md documents this correction).
Model selection — LocalModelSelector.ts:75 selectDefaultImageModel: ≥24 GB → sd3.5_large, ≥16 GB → flux1-schnell, else SDXL. canRunLTXVideo (:187) gates on ≥14 GB RAM; canRunBriaRMBG (:196) on ≥3 GB.
Two concrete defects in this path:
setup-comfyui.sh:128cloneskijai/ComfyUI-RMBG— the 404 URL that the GPU-side script explicitly fixed to1038lab/ComfyUI-RMBG(startup_script.sh:64-66), and whichstartup_script_test.go:103-107now asserts against. The desktop path still has the broken URL.CapabilityAdvisor.tsis atweb/electron/main/briareus/CapabilityAdvisor.ts, notweb/electron/main/backends/CapabilityAdvisor.tsas cited bydocs/planning/26.35/os-video-model-integration/README.mdand the migration header — and it contains no ComfyUI or local-backend logic at all (127 lines, chat-model budget only:assessModel,recommendChatModel). The migration's claim that it "drives the two-path runnability check" for ComfyUI is not true of this file.deriveHardwareProfile, also cited, does not exist there.
Planned but NOT built
| Claim | Doc that claims it | Reality at ef3798123c5 |
|---|---|---|
| "Planning. Nothing built." | docs/planning/26.35/os-video-model-integration/README.md:3 | Stale. Phase 1 (catalog, routing, licence pins, tier readers) is live in production per status/M3.md |
| "No ComfyUI workflow graphs for video." | docs/planning/26.35/status/M3.md (last updated 2026-08-27) | Stale. Four video graphs exist; three GPU-verified (2026-08-26/28). The workflow files post-date the doc |
h200 GPU tier | README.md Phase 2; 20260831130100 column comment | Not added. "H200 appears only as a costing line in the 26.36 Kimi K3 plan" |
| Customer-hardware VRAM floors for the new models | 20260831130000 header; 20260831130100 customer-tier rows | Not measured. local_backend_type/local_min_* stay NULL → CapabilityAdvisor reads non-local → models not offered on customer hardware. 08-measurements.md is the empty ledger |
| Control / LoRA runtime graphs | 04-control-and-lora-assets.md §4.3 | ControlBlock exists in generation_types.go:82 and travels the wire, but connector_comfyui.go:220-231 hard-errors on any control request. Adapters are seeded in the DB (20260831130200) with no graph to consume them |
services/comfyui-service render node | docs/planning/26.28/atlas-2d3d-character-pipeline/README.md:138 | Does not exist. The contentstudio façade that would call it (POST {COMFYUI_API_URL}/render) is unreachable |
| Apple Silicon measurement | 03-apple-silicon.md | Nothing measured; is_supported NULL for every customer_apple row except the incumbent LTX-Video |
| Horror-corpus training pipeline | 05-training-pipeline.md | Phase 5, gated on Phase 0 |
comfyui_lrm Layer-2 param rendering | internal/modelparams/transport.go:168-185 | No driver registered; Layer-1 coercion only |
| Async-handoff for local media | docs/planning/26.28/local-magieva/04-comfyui-media-activation.md ("🔴 Remaining: #14 (deferred)") | Still deferred |
Staging e2e for i2i (input_image_url consumption) | same doc, "Staging-verify the LRM ComfyUI connector actually consumes input_image_url" | Still open |
Reusable in a competition entry
Directly reusable as an open-source ComfyUI app (little or no Magieva-internal coupling):
- The workflow-graph corpus + the (capability × model) keying discipline.
comfyui_workflows/*.jsonare ComfyUI's own templates exported to API format, with_READMEblocks recording provenance, upstream version, and measured wall-clock/peak-VRAM. TheworkflowTemplateKeydesign (comfyui_workflows.go:37-44) and the rule "a model with no template must FAIL, naming the model" is a genuinely good pattern for any multi-model ComfyUI app. comfyui_workflow_params.goin full. Graph-agnostic injection matching onclass_typeand following the graph's own links — survives a re-export that renumbers nodes. TheisLinkguard (never overwrite a link with a literal,:45-54) andfindPromptNodes(resolve positive vs negative by following links,:91) are the two pieces that make it robust. This is the single most reusable file in the inventory.- The connector's output-extraction layer.
comfyOutputKeys+comfyMimeByExt+sortOutputsRichestFirstencode hard-won knowledge (coreSaveVideoemits underimages) that any ComfyUI client needs. - The fail-loud guards. Refusing to answer a video request with a txt2img PNG, and refusing control requests that nothing honours, are the right defaults and are cheap to port.
setup-comfyui.sh— a working, idempotent macOS/Linux ComfyUI installer (once the RMBG URL is fixed to1038lab).- The licence-classification idea — separating code licence from weight licence, with most-restrictive-wins and per-adapter classification. Reusable as a concept even if the specific pins are Magieva's.
Magieva-internal plumbing that would need replacing:
- LRM itself. The whole
/v1/generate+/v1/generate/async+/api/v1/local/backendssurface,LocalBackend,Origin(customer_device/platform_gpu), theX-Organization-IDattribution header,LocalUsageRecorder, and the token-hold billing gate. A competition app would talk to ComfyUI directly. - The AIMRS resolution layer.
ExecuteLocalGenerationdepends on a resolvedEndpointURLandIsLocal()from a separate routing service. Not portable. - The GCE provisioner + tier catalog.
provisioner_gce.go,gpuTiers,ai_model_execution_tiers,ai_model_adapters— cloud-specific. internal/modellicense's enforcement points (org_license_acceptances,platform_gpuorigin) — the policy is reusable, the enforcement is Magieva's DB.- The desktop event-bridge registration (
sendBackendReady→ event-bridge → LRM) — three services deep. internal/psdedit/local.goand thecontentstudiofaçade — both currently broken; do not port as-is.
Judgement. The reusable core is roughly comfyui_workflow_params.go + comfyui_workflows.go + comfyui_workflows/*.json + the connector's submit/poll/extract half — a self-contained "ComfyUI workflow runner with model-keyed graphs and safe param injection." Everything else is either Magieva's multi-tenant routing/billing substrate or an unwired seam.
Gaps and unknowns
Verified gaps (code-level, no runtime needed):
internal/psdedit/local.go:72targets a non-existent route; its payload field would be dropped even if the route existed. The local PSD-edit path cannot work.COMFYUI_API_URLis set nowhere in deployment config;services/comfyui-servicedoes not exist. ThecontentstudioControlNet ComfyUI path is dead code.comfyui_lrmhas no registered transport driver.setup-comfyui.sh:128still clones the 404kijai/ComfyUI-RMBG.- Sync vs async vs images billing-gate asymmetry: platform-GPU ComfyUI is rejected on
/v1/generatebut accepted and unbilled on/v1/generate/asyncand/v1/images/generations. lrm_client.go:66-69registers every ComfyUI runner asbackend_type: "image", even when provisioned for a video capability.- Customer docs (
comfyui--local.md) list 19 models; only 4 have registered graphs.
Not verified / unknown (stated rather than guessed):
- I did not run
go test,go build, or any service. "Live" above means wired in code and reachable by a registered route/caller, not observed running. - I did not read
services/local-resource-manager/backend_handler.goin full, so I cannot state whether the registration gate and the generation gate agree on every backend type; I verified only theorigin=platform_gpuhosted-model licence check at:224. - I did not verify the
ai_model_adaptersmigration (20260831130200) contents beyond its header. - I did not confirm whether the
first_last_frame_to_videogap is still open in a later commit —GenerationRequestat this commit carries oneInputImageURLonly (generation_types.go:50). - The
docs/planning/26.35/status/M3.mdproduction claims (live in26.35.5, 0local_backendsrows,dryrunprovisioner) are the doc's assertions; I did not query any environment. internal/contentstudio/is another agent's scope; I read only theCOMFYUI_API_URLfaçade (character_render_controlnet.go:160-274).- I did not exhaustively enumerate every
_test.goassertion; test files are cited as evidence of intent and coverage, not audited line by line.