fix(swarm-matrix): bake a variant payload for every app the round deploys

The swarm matrix resolved variant payloads over the planner's round_include while provisioning the closure derive_includes returns. The two agree until a variant switches its couplings off: the planner then resolves no prerequisites, round_include collapses to the primary, and every deployed dependency silently keeps its base config. For svc-ai-litellm round 1 that meant web-app-keycloak ran with the base realm.totp_enabled true, so CONFIGURE_TOTP became a default required action and every SSO persona sat in a 300s predicate timeout until the job hit its wall clock at 20086s.

payload.py states the intent this restores: the role pulling a dependency in is what decides how lean the dependency runs. variant_scope keeps the decision next to the closure it filters and excludes the three lab infrastructure roles, whose payload would replace group-membership expressions such as {{ 'svc-swarm-node' in group_names }} with an unconditional true in every round.

Measured: round 1 goes from 1 to 29 payload apps and keycloak from absent to totp_enabled false, while the deployed closure stays 32. Repo-wide 62 of 280 rounds gain a real setting, dominated by postgres exposed in 48 and mariadb in 22; no round loses one, and no gained payload enables a service whose provider is not deployed. With disable set the scope shrinks instead, which is correct because a pruned provider is not deployed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-09-16 13:10:16 +02:00
1 parent 92eb58f38a
commit e1d513a3c0
2 files changed
+17 -2

No files matched your search

+15
View File
@@ -193,6 +193,21 @@ def derive_includes(
return sorted(found)
def variant_scope(app_id: str, *, variants: dict[str, int] | None = None) -> list[str]:
"""Deployed roles for APP_ID that must carry their own variant config.
Args:
app_id: role whose closure is resolved.
variants: active ``{app_id: variant_index}`` map, as ``derive_includes``.
"""
explicit = set(_EXPLICIT_INCLUDES) - {app_id}
return [
role
for role in derive_includes(app_id, variants=variants)
if role not in explicit
]
def _disabled_provider_roles(service_registry: dict[str, Any]) -> set[str]:
"""Provider roles the ``disable`` env removes from the closure, so the
swarm include set matches what the provision-time services_disabler
+2 -2
View File
@@ -29,7 +29,7 @@ import time
from utils import PROJECT_ROOT
from utils.env.runtime import mem_available_mb, mem_stall_pct, mem_total_mb
from utils.storage.constrained import host_storage_constrained
from utils.tests.swarm.derive_includes import derive_includes
from utils.tests.swarm.derive_includes import derive_includes, variant_scope
from utils.tests.swarm.write.extras import ensure_swarm_keypairs
_SWARM_DIR = PROJECT_ROOT / "scripts" / "tests" / "deploy" / "swarm"
@@ -397,7 +397,7 @@ def main(argv: list[str] | None = None) -> int:
variant_payloads = _resolve_variant_payloads(
roles_dir=_ROLES_DIR,
include=round_include,
include=variant_scope(app_id, variants=round_variants),
active_variants=round_variants,
)
from utils.tests.swarm.backup_repos import backup_provider_ips