Document Regional legacy removal windows

This commit is contained in:
BlackVortexAI
2026-08-25 07:18:35 +02:00
parent a4d57e65b0
commit 2a83efbbe5
6 changed files with 38 additions and 0 deletions
+21
View File
@@ -68,6 +68,8 @@ CATEGORY_MODEL_FLUX2_KLEIN = f"{CATEGORY_MODELS}/FLUX.2 Klein 9B"
CATEGORY_MODEL_KREA2 = f"{CATEGORY_MODELS}/Krea 2"
CATEGORY_MODEL_ANIMA = f"{CATEGORY_MODELS}/Anima"
DEFAULT_JSON = json.dumps(default_document(), ensure_ascii=False, separators=(",", ":"))
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA bindings JSON/output.
# Remove with the lora_bindings output after saved V2 workflows have passed the compatibility window.
DEFAULT_LORA_BINDINGS_JSON = json.dumps(default_bindings(), ensure_ascii=False, separators=(",", ":"))
DEFAULT_LORA_V3_JSON = '{"version":3,"entries":[],"steps":[]}'
DEFAULT_DETAILER_V3_JSON = '{"version":1,"jobs":[]}'
@@ -108,6 +110,8 @@ class BVRegionalPromptNode:
),
},
"optional": {
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Persisted V2 bindings payload.
# Remove with the lora_bindings output after workflow migration support expires.
"lora_bindings_json": (
"STRING",
{"default": DEFAULT_LORA_BINDINGS_JSON, "multiline": True, "dynamicPrompts": False},
@@ -129,6 +133,7 @@ class BVRegionalPromptNode:
},
}
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Second output is V2 wiring.
RETURN_TYPES = (REGIONAL, BINDINGS)
RETURN_NAMES = ("regional", "lora_bindings")
FUNCTION = "build"
@@ -180,6 +185,8 @@ class BVLoraStackCollectorNode:
def INPUT_TYPES(cls):
return {
"required": {
# BV-LEGACY(marked=2026-08-25, review-after=2026-10-25): V2 stack registry bridge.
# Remove only when named stacks expose the V3 provider contract without this adapter.
"lora_registry": (REGISTRY, {}),
"collector_id": ("STRING", {"default": "", "multiline": False}),
}
@@ -235,6 +242,8 @@ def _context_lora_scopes(regional):
def _consumer_lora_scopes(regional, document, lora_registry=None, lora_bindings=None):
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Prefer the V3 context capability.
# Remove this sidecar fallback together with every lora_registry/lora_bindings consumer port.
if lora_registry is not None or lora_bindings is not None:
return resolve_scope_stacks(lora_registry, lora_bindings, document)
return _context_lora_scopes(regional)
@@ -500,6 +509,7 @@ class BVRegionalNativeConditioningNode:
},
),
},
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA sidecar inputs.
"optional": {"lora_registry": (REGISTRY, {}), "lora_bindings": (BINDINGS, {})},
}
@@ -544,6 +554,7 @@ class BVRegionalSDXLAttentionNode:
{"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001},
),
},
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA sidecar inputs.
"optional": {"lora_registry": (REGISTRY, {}), "lora_bindings": (BINDINGS, {})},
}
@@ -588,6 +599,7 @@ class BVRegionalZImageAttentionNode:
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
"end_percent": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}),
},
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA sidecar inputs.
"optional": {"lora_registry": (REGISTRY, {}), "lora_bindings": (BINDINGS, {})},
}
@@ -624,6 +636,7 @@ class BVRegionalFlux2KleinAttentionNode:
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
"end_percent": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}),
},
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA sidecar inputs.
"optional": {"lora_registry": (REGISTRY, {}), "lora_bindings": (BINDINGS, {})},
}
@@ -667,12 +680,15 @@ class BVRegionalKrea2AttentionNode:
"attention_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
"end_percent": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}),
# BV-LEGACY(marked=2026-08-25, review-after=2026-10-25): Compatibility execution mode.
# Remove only after token-gated Krea 2 matches supported published LoRA behavior.
"regional_lora_mode": (["multipass_legacy", "token_gated_singlepass"], {
"default": "token_gated_singlepass",
"tooltip": "Legacy evaluates one masked model pass per distinct LoRA stack. "
"Token-gated single-pass is experimental and changes results.",
}),
},
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA sidecar inputs.
"optional": {"lora_registry": (REGISTRY, {}), "lora_bindings": (BINDINGS, {})},
}
@@ -709,6 +725,7 @@ class BVRegionalKrea2AttentionNode:
positive, negative, slots, aspect_ratio = compile_krea2_attention(
document, clip, hook_groups
)
# BV-LEGACY(marked=2026-08-25, review-after=2026-10-25): See the INPUT_TYPES removal gate above.
if regional_lora_mode == "multipass_legacy":
positive, negative = apply_attention_hook_passes(
positive, negative, document, scope_stacks, hook_groups
@@ -760,11 +777,14 @@ class BVRegionalAnimaConditioningNode:
"base_ratio": ("FLOAT", {"default": 0.1, "min": 0.0, "max": 1.0, "step": 0.01}),
"cross_inject_every_n_blocks": ("INT", {"default": 1, "min": 1, "max": 100, "step": 1}),
"self_inject_every_n_blocks": ("INT", {"default": 1, "min": 1, "max": 100, "step": 1}),
# BV-LEGACY(marked=2026-08-25, review-after=2026-10-25): Compatibility execution mode.
# Remove only after token-gated Anima matches supported published LoRA behavior.
"regional_lora_mode": (["multipass_legacy", "token_gated_singlepass"], {
"default": "multipass_legacy",
"tooltip": "Legacy preserves published Anima results. Single-pass is an experimental token-gated model-LoRA path.",
}),
},
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 LoRA sidecar inputs.
"optional": {"lora_registry": (REGISTRY, {}), "lora_bindings": (BINDINGS, {})},
}
@@ -809,6 +829,7 @@ class BVRegionalAnimaConditioningNode:
scope_stacks = resolve_stack_paths(_consumer_lora_scopes(regional, document, lora_registry, lora_bindings))
hook_groups = create_hook_groups(scope_stacks)
positive, negative, regions, background = compile_anima_adapter(document, clip, hook_groups)
# BV-LEGACY(marked=2026-08-25, review-after=2026-10-25): See the INPUT_TYPES removal gate above.
if regional_lora_mode == "multipass_legacy":
positive, negative = apply_attention_hook_passes(
positive, negative, document, scope_stacks, hook_groups
+7
View File
@@ -68,6 +68,8 @@ class BVRegionalDetailerPlanNode:
"config_json": ("STRING", {"default": "", "multiline": True}),
},
"optional": {
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): V2 detector sidecar input.
# Remove after migrated plans resolve detectors exclusively through V3 provider links.
"detector_registry": (DETECTOR_REGISTRY, {}),
"resource_provider": (RUNTIME_PROVIDER, {"forceInput": True}),
**{
@@ -118,6 +120,7 @@ class BVRegionalDetailerPlanNode:
detector_id = job.get("detector_id")
if detector_id is not None:
resolve_detector(detector_registry, detector_id)
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Preserve V2 executor lookup.
plan["detector_registry"] = detector_registry
summary = "\n".join(
f"{index + 1}. {' + '.join(job['region_names'])}"
@@ -161,6 +164,7 @@ class BVRegionalDetailerJobNode:
raise ValueError("BV Detailer Loop Job Resolver requires a single IMAGE shaped B,H,W,C")
job = detailer_job_at(detailer_plan, job_index)
detector_id = job.get("detector_id")
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Execute unmigrated V1/V2 jobs.
if "detector_binding" not in job:
job["detector_binding"] = (
resolve_detector(detailer_plan.get("detector_registry"), detector_id)
@@ -231,6 +235,8 @@ class BVDetectorRegistryNode:
},
}
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): First output is the V2 registry.
# Remove it only with the detector_registry plan input; resource_provider is the V3 output.
RETURN_TYPES = (DETECTOR_REGISTRY, "INT", "STRING", RUNTIME_PROVIDER)
RETURN_NAMES = ("detector_registry", "detector_count", "registry_summary", "resource_provider")
FUNCTION = "collect"
@@ -252,6 +258,7 @@ class BVDetectorRegistryNode:
}
except json.JSONDecodeError as error:
raise ValueError("detector registry configuration is invalid JSON") from error
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Accept config v1 without collector_id.
if not isinstance(parsed, dict) or parsed.get("schema") != "bv.detector_registry_config" or parsed.get("version") not in {1, 2}:
raise ValueError("detector registry configuration must be bv.detector_registry_config v1 or v2")
collector_id = str(parsed.get("collector_id", "")).strip() if parsed.get("version") == 2 else ""
+2
View File
@@ -280,6 +280,8 @@ def materialize_detailer_plan(
return plan
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Legacy plan -> V3 resource bindings.
# Remove after saved plans carry explicit same-graph collector_id/resource_id pairs.
def migrate_detailer_plan_v1(
value: Any,
config: Any,
+2
View File
@@ -249,6 +249,8 @@ def validate_document(document: Any, *, executable: bool = True) -> list[str]:
return list(dict.fromkeys(issues))
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Regional document v1 -> v2.
# Remove only after published/saved v1 workflows have passed the compatibility window.
def migrate_document(document: Any) -> dict[str, Any]:
migrated = copy.deepcopy(document)
if not isinstance(migrated, dict) or migrated.get("schema") != "bv.regional":
+4
View File
@@ -113,6 +113,8 @@ def validate_lora_capability(payload: dict[str, Any]) -> None:
}})
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): LoRA capability v1 -> v2.
# Remove together with v1 validation/registration after old workflows have migrated.
def migrate_lora_capability_v1(payload: dict[str, Any]) -> dict[str, Any]:
validate_lora_capability(payload)
collector_id = payload["collector_id"]
@@ -127,6 +129,8 @@ def migrate_lora_capability_v1(payload: dict[str, Any]) -> dict[str, Any]:
return migrated
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): LoRA capability v2 -> v3.
# Remove together with v2 validation/registration after old workflows have migrated.
def migrate_lora_capability_v2(payload: dict[str, Any]) -> dict[str, Any]:
validate_lora_capability(payload)
migrated = {"version": 3, "entries": payload["entries"], "scopes": {}}
+2
View File
@@ -101,6 +101,8 @@ def _feather(mask: torch.Tensor, amount: float, width: int, height: int) -> torc
def render_region(region: dict[str, Any], width: int, height: int) -> torch.Tensor:
layers: dict[str, list[dict[str, Any]]] = {}
# BV-LEGACY(marked=2026-08-25, remove-after=2026-10-25): Pre-layer geometry fallback.
# Remove after documents without layer_id are no longer accepted by document migration.
legacy_layer = next((shape["id"] for shape in region["geometry"] if "layer_id" not in shape), "__legacy__")
for shape in region["geometry"]:
layer_id = shape.get("layer_id", legacy_layer)