From 52b02d773aa4633f3417ab999562e9ab2b2f3d62 Mon Sep 17 00:00:00 2001 From: Rafael Lopez Date: Mon, 12 Oct 2026 00:42:48 -0500 Subject: [PATCH] fix(P0): route Intel/AMD and registered internal agents through one provider registry --- .../agent_provider_registry.py | 14 ++++-- .../inneros_core_runtime/execution_binding.py | 15 +++--- platform/tests/test_execution_binding.py | 50 +++++++++++++++++++ 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/platform/inneros_core_runtime/agent_provider_registry.py b/platform/inneros_core_runtime/agent_provider_registry.py index c556f970..4119a40e 100644 --- a/platform/inneros_core_runtime/agent_provider_registry.py +++ b/platform/inneros_core_runtime/agent_provider_registry.py @@ -9,7 +9,11 @@ from inneros_core_runtime import agent_identity _DEFAULT_IDE = frozenset({"cursor", "codex", "antigravity", "gemini", "chatgpt"}) -_DEFAULT_INTERNAL = frozenset({"local", "dev_swarm", "dev-swarm", "temporal", "local-amd-5"}) +_DEFAULT_INTERNAL = frozenset({ + "local", "dev_swarm", "dev-swarm", "temporal", + # Actor mailboxes use underscores, while execution providers use hyphens. + "local-amd-5", "local_amd_5", "local-intel-4", "local_intel_4", +}) _REGISTRY: dict[str, dict[str, Any]] = {} @@ -51,7 +55,7 @@ def register_interactive_provider( def register_internal_provider(provider: str, *, default_lane: str = "local_dev_swarm") -> dict[str, Any]: - key = _slug(provider) + key = agent_identity.canonical_mailbox(provider, default=_slug(provider)) doc = {"provider": key, "kind": "internal_bounded", "default_lane": default_lane, "do_not_auto_dispatch_default": False} _REGISTRY[key] = doc return {"ok": True, "registered": doc} @@ -93,8 +97,10 @@ def apply_create_ops_defaults( lane = f"{prov}_interactive" if do_not_auto_dispatch is None: do_not_auto_dispatch = True - elif prov in internal_providers() and not lane: - lane = "local_dev_swarm" + elif prov in internal_providers(): + lane = lane or "local_dev_swarm" + if do_not_auto_dispatch is None: + do_not_auto_dispatch = False return lane or None, prov, do_not_auto_dispatch diff --git a/platform/inneros_core_runtime/execution_binding.py b/platform/inneros_core_runtime/execution_binding.py index db670ebc..dcfb65e8 100644 --- a/platform/inneros_core_runtime/execution_binding.py +++ b/platform/inneros_core_runtime/execution_binding.py @@ -19,6 +19,13 @@ def _ide_providers() -> frozenset[str]: return _interactive_ide_providers() except Exception: return INTERACTIVE_IDE_PROVIDERS + + +def _internal_providers() -> frozenset[str]: + """Use the same normalized, extensible provider set as task admission.""" + from inneros_core_runtime import agent_provider_registry as apr + + return frozenset(normalize_provider(p) for p in apr.internal_providers()) INTERNAL_BOUNDED_RUNNER = "internal_bounded_local" INTERACTIVE_IDE_RUNNER = "interactive_ide_handoff" CURSOR_INTERACTIVE_RUNNER = "cursor_interactive" @@ -331,13 +338,7 @@ def blocked(error: str, message: str, status: str = "waiting_for_binding") -> di "message": f"Esperando claim/ejecución en sesión {provider}.", } - if lane in {"internal", "local_dev_swarm", "dev_swarm"} or provider in { - "local", - "local-amd-5", - "dev_swarm", - "dev-swarm", - "temporal", - }: + if lane in {"internal", "local_dev_swarm", "dev_swarm"} or provider in _internal_providers(): # The internal bounded runner creates a governed Git worktree. Without # a real owner/repo it cannot execute an infrastructure request, even # when a local model generates convincing instructions. diff --git a/platform/tests/test_execution_binding.py b/platform/tests/test_execution_binding.py index 350b042b..25a55c2c 100644 --- a/platform/tests/test_execution_binding.py +++ b/platform/tests/test_execution_binding.py @@ -5,6 +5,7 @@ import unittest from inneros_core_runtime import execution_binding as eb +from inneros_core_runtime import agent_provider_registry as apr from inneros_core_runtime import temporal_activities as ta @@ -85,6 +86,55 @@ def test_owner_summary_explains_codex_not_internal(self) -> None: self.assertTrue(summary["requires_owner_authorization"]) self.assertIn("Dev Swarm", summary["internal_alternative"]) + def test_local_amd_and_intel_internal_defaults_match_binding(self) -> None: + for provider in ("local-amd-5", "local-intel-4"): + with self.subTest(provider=provider): + lane, effective_provider, no_auto = apr.apply_create_ops_defaults( + "dev_swarm", execution_lane=None, preferred_provider=provider, + do_not_auto_dispatch=None, + ) + self.assertEqual(lane, "local_dev_swarm") + self.assertFalse(no_auto) + self.assertIn(effective_provider, apr.internal_providers()) + binding = eb.resolve_execution_binding({ + "task_id": "ops_local_symmetry", + "preferred_provider": provider, + "repo": "Rafa-Innerchispa/innerops-agentic-platform", + }) + self.assertTrue(binding["allowed"], binding) + self.assertEqual(binding["runner"], eb.INTERNAL_BOUNDED_RUNNER) + + def test_registered_internal_provider_binds_without_hardcoded_list(self) -> None: + apr.register_internal_provider("local-test-edge") + binding = eb.resolve_execution_binding({ + "task_id": "ops_new_internal", + "preferred_provider": "local-test-edge", + "repo": "Rafa-Innerchispa/innerops-agentic-platform", + }) + self.assertTrue(binding["allowed"], binding) + lane, _, no_auto = apr.apply_create_ops_defaults( + "dev_swarm", execution_lane=None, + preferred_provider="local-test-edge", do_not_auto_dispatch=None, + ) + self.assertEqual(lane, "local_dev_swarm") + self.assertFalse(no_auto) + + def test_owner_explicit_no_autodispatch_not_overridden(self) -> None: + lane, _, no_auto = apr.apply_create_ops_defaults( + "dev_swarm", execution_lane=None, + preferred_provider="local-intel-4", do_not_auto_dispatch=True, + ) + self.assertEqual(lane, "local_dev_swarm") + self.assertTrue(no_auto) + binding = eb.resolve_execution_binding({ + "task_id": "ops_intel_blocked", + "preferred_provider": "local-intel-4", + "repo": "Rafa-Innerchispa/innerops-agentic-platform", + "do_not_auto_dispatch": True, + }) + self.assertFalse(binding["allowed"]) + self.assertEqual(binding["error"], "do_not_auto_dispatch") + def test_internal_dev_swarm_allowed(self) -> None: binding = eb.resolve_execution_binding( {