test(actor): add @tdd_issue_1429 regression tests for actor_ref field reading
CI / push-validation (pull_request) Successful in 19s
CI / helm (pull_request) Successful in 30s
CI / lint (pull_request) Successful in 44s
CI / build (pull_request) Successful in 47s
CI / quality (pull_request) Successful in 50s
CI / typecheck (pull_request) Successful in 1m4s
CI / security (pull_request) Successful in 1m16s
CI / unit_tests (pull_request) Successful in 6m12s
CI / docker (pull_request) Successful in 1m23s
CI / coverage (pull_request) Successful in 16m5s
CI / integration_tests (pull_request) Successful in 22m39s
CI / status-check (pull_request) Successful in 2s

Add Behave feature file and Robot Framework integration tests covering
the two compiler functions fixed in issue #1429:

- _map_node(): SUBGRAPH node's NodeConfig.subgraph is now populated from
  node.actor_ref instead of config.get("actor_ref") which always returned None
- compile_actor(): metadata.subgraph_refs is now populated from
  node_def.actor_ref instead of node_def.config.get("actor_ref", "") which
  always returned an empty string

Three Behave scenarios tagged @tdd_issue @tdd_issue_1429 covering:
  1. NodeConfig.subgraph field populated from actor_ref (_map_node fix)
  2. metadata.subgraph_refs populated from actor_ref (compile_actor fix)
  3. Both fields correct together with a realistic actor ref

Two Robot Framework integration tests in tdd_actor_compiler_actor_ref_1429.robot
with a self-contained Python helper that exercises both code paths in isolation.

ISSUES CLOSED: #1429
This commit is contained in:
2026-05-29 23:18:31 -04:00
committed by Forgejo
parent 30c2953e9f
commit 2c2b4e8813
3 changed files with 235 additions and 0 deletions
@@ -0,0 +1,157 @@
"""Robot Framework helper for tdd_actor_compiler_actor_ref_1429 tests.
Regression tests for issue #1429: the actor compiler must read actor_ref
from NodeDefinition.actor_ref (a typed Pydantic field), not from
node.config.get("actor_ref") (a raw dict lookup).
Two aspects are tested:
subgraph-field -- _map_node() sets NodeConfig.subgraph from node.actor_ref
subgraph-refs -- compile_actor() populates metadata.subgraph_refs from
node_def.actor_ref
Usage:
python robot/helper_tdd_actor_compiler_actor_ref_1429.py subgraph-field
python robot/helper_tdd_actor_compiler_actor_ref_1429.py subgraph-refs
"""
from __future__ import annotations
import sys
from pathlib import Path
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
from cleveragents.actor.compiler import compile_actor # noqa: E402
from cleveragents.actor.schema import ( # noqa: E402
ActorConfigSchema,
ActorType,
EdgeDefinition,
NodeDefinition,
NodeType,
RouteDefinition,
)
_ACTOR_REF = "local/code-reviewer"
def _make_outer_actor() -> ActorConfigSchema:
"""GRAPH actor with one AGENT node and one SUBGRAPH node referencing _ACTOR_REF."""
nodes = [
NodeDefinition(
id="start",
type=NodeType.AGENT,
name="Start",
description="Start node",
config={"agent": "default"},
),
NodeDefinition(
id="sub",
type=NodeType.SUBGRAPH,
name="Sub",
description="Subgraph node",
config={},
actor_ref=_ACTOR_REF,
),
]
route = RouteDefinition(
nodes=nodes,
edges=[EdgeDefinition(from_node="start", to_node="sub")],
entry_node="start",
exit_nodes=["sub"],
)
return ActorConfigSchema(
name="test/outer-1429",
type=ActorType.GRAPH,
description="Outer actor for #1429 regression test",
provider="openai",
model="gpt-4",
route=route,
)
def _make_inner_actor() -> ActorConfigSchema:
"""Simple leaf GRAPH actor with no subgraph nodes."""
nodes = [
NodeDefinition(
id="leaf",
type=NodeType.AGENT,
name="Leaf",
description="Leaf node",
config={"agent": "default"},
)
]
route = RouteDefinition(
nodes=nodes,
edges=[],
entry_node="leaf",
exit_nodes=["leaf"],
)
return ActorConfigSchema(
name=_ACTOR_REF,
type=ActorType.GRAPH,
description="Inner actor for #1429 regression test",
provider="openai",
model="gpt-4",
route=route,
)
def main() -> int:
if len(sys.argv) < 2:
print(
"Usage: helper_tdd_actor_compiler_actor_ref_1429.py"
" <subgraph-field|subgraph-refs>"
)
return 1
command = sys.argv[1]
outer = _make_outer_actor()
inner = _make_inner_actor()
registry = {outer.name: outer, inner.name: inner}
if command == "subgraph-field":
# Tests _map_node(): NodeConfig.subgraph must be set from node.actor_ref
try:
compiled = compile_actor(outer, actor_resolver=registry.get)
node_cfg = compiled.nodes.get("sub")
if node_cfg is None:
print("tdd-1429-subgraph-field-fail: 'sub' not in compiled.nodes")
return 1
if node_cfg.subgraph != _ACTOR_REF:
print(
f"tdd-1429-subgraph-field-fail: "
f"expected subgraph={_ACTOR_REF!r}, got {node_cfg.subgraph!r}"
)
return 1
print(f"tdd-1429-subgraph-field-ok: subgraph={node_cfg.subgraph!r}")
return 0
except Exception as exc:
print(f"tdd-1429-subgraph-field-error: {exc}")
return 1
if command == "subgraph-refs":
# Tests compile_actor(): metadata.subgraph_refs must be populated
# from node_def.actor_ref
try:
compiled = compile_actor(outer, actor_resolver=registry.get)
refs = compiled.metadata.subgraph_refs
if refs.get("sub") != _ACTOR_REF:
print(
f"tdd-1429-subgraph-refs-fail: "
f"expected subgraph_refs['sub']={_ACTOR_REF!r}, got {refs!r}"
)
return 1
print(f"tdd-1429-subgraph-refs-ok: subgraph_refs={refs!r}")
return 0
except Exception as exc:
print(f"tdd-1429-subgraph-refs-error: {exc}")
return 1
print(f"Unknown command: {command}")
return 1
if __name__ == "__main__":
sys.exit(main())
@@ -0,0 +1,39 @@
*** Settings ***
Documentation TDD regression tests for issue #1429: actor compiler reads
... actor_ref from NodeDefinition.actor_ref field, not from the
... raw node.config dict.
...
... Two compiler functions are covered:
... _map_node() -- sets NodeConfig.subgraph
... compile_actor() -- populates metadata.subgraph_refs
Resource ${CURDIR}/common.resource
Suite Setup Setup Test Environment
Suite Teardown Cleanup Test Environment
*** Variables ***
${HELPER} ${CURDIR}/helper_tdd_actor_compiler_actor_ref_1429.py
*** Test Cases ***
NodeConfig subgraph Set From actor_ref Field In _map_node
[Documentation] Verify _map_node() reads actor_ref from NodeDefinition.actor_ref
... so that NodeConfig.subgraph is populated for SUBGRAPH nodes.
... Before the fix for #1429 this always returned None because the compiler
... used config.get("actor_ref") on a dict that never contained the key.
[Tags] slow
${result}= Run Process ${PYTHON} ${HELPER} subgraph-field cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} tdd-1429-subgraph-field-ok
Metadata subgraph_refs Populated From actor_ref Field In compile_actor
[Documentation] Verify compile_actor() reads actor_ref from NodeDefinition.actor_ref
... so that metadata.subgraph_refs maps SUBGRAPH node IDs to referenced actor names.
... Before the fix for #1429 subgraph_refs was always empty because the compiler
... used node_def.config.get("actor_ref", "") on a dict that never contained the key.
[Tags] slow
${result}= Run Process ${PYTHON} ${HELPER} subgraph-refs cwd=${WORKSPACE}
Log ${result.stdout}
Log ${result.stderr}
Should Be Equal As Integers ${result.rc} 0
Should Contain ${result.stdout} tdd-1429-subgraph-refs-ok