Files
cleveragents-core/features/steps/workflow_parity_steps.py
T
2025-11-24 20:04:18 -05:00

314 lines
11 KiB
Python

"""Step definitions for workflow parity feature."""
import json
from pathlib import Path
from behave import given, then, when
from cleveragents.discovery.workflow_parity import WorkflowParityExtractor
@given("the workflow parity extractor is initialized")
def step_init_workflow_extractor(context):
"""Initialize the workflow parity extractor."""
plandex_dir = Path(__file__).parent.parent.parent / "plandex"
context.workflow_extractor = WorkflowParityExtractor(plandex_dir)
@when("I run the workflow parity extraction")
def step_run_workflow_extraction(context):
"""Run the workflow extraction."""
context.workflow_results = context.workflow_extractor.extract_all()
@when("I extract workflows and generate the parity matrix")
def step_extract_and_generate_matrix(context):
"""Extract workflows and generate parity matrix."""
context.workflow_results = context.workflow_extractor.extract_all()
context.parity_matrix = context.workflow_results["matrix"]
@when("I extract plan-related workflows")
def step_extract_plan_workflows(context):
"""Extract plan lifecycle workflows."""
context.workflow_extractor._extract_plan_workflows()
context.plan_workflows = {
k: v
for k, v in context.workflow_extractor.workflows.items()
if v.get("category") == "plan_lifecycle"
}
@when("I extract context workflows")
def step_extract_context_workflows(context):
"""Extract context management workflows."""
context.workflow_extractor._extract_context_workflows()
context.context_workflows = {
k: v
for k, v in context.workflow_extractor.workflows.items()
if v.get("category") == "context_management"
}
@when("I extract execution workflows")
def step_extract_execution_workflows(context):
"""Extract execution workflows."""
context.workflow_extractor._extract_exec_workflows()
context.exec_workflows = {
k: v
for k, v in context.workflow_extractor.workflows.items()
if v.get("category") == "execution_flows"
}
@when("I extract all workflows")
def step_extract_all_workflows(context):
"""Extract all workflows."""
context.workflow_results = context.workflow_extractor.extract_all()
@given("I have extracted workflow mappings")
def step_have_workflow_mappings(context):
"""Ensure workflow mappings are extracted."""
if not hasattr(context, "workflow_results"):
context.workflow_results = context.workflow_extractor.extract_all()
@when("I save the workflow parity results")
def step_save_workflow_results(context):
"""Save workflow parity results."""
output_dir = Path("build/test_output/workflows")
context.json_file, context.yaml_file = context.workflow_extractor.save_results(
output_dir
)
@then("I should get workflow mappings for all categories")
def step_check_workflow_categories(context):
"""Check that all categories have workflows."""
context.workflow_results["categories"]
workflows = context.workflow_results["workflows"]
# Check that we have workflows in multiple categories
workflow_categories = set(w.get("category") for w in workflows.values())
assert len(workflow_categories) > 5, (
f"Expected multiple categories, got {workflow_categories}"
)
@then("each workflow should have Go components mapped")
def step_check_go_components(context):
"""Check that workflows have Go components."""
workflows = context.workflow_results["workflows"]
for workflow_id, workflow in workflows.items():
assert "go_components" in workflow, f"Missing go_components in {workflow_id}"
assert len(workflow["go_components"]) > 0, f"No Go components in {workflow_id}"
@then("each workflow should have Python modules assigned")
def step_check_python_modules(context):
"""Check that workflows have Python modules."""
workflows = context.workflow_results["workflows"]
for workflow_id, workflow in workflows.items():
assert "python_modules" in workflow, f"Missing python_modules in {workflow_id}"
assert len(workflow["python_modules"]) > 0, (
f"No Python modules in {workflow_id}"
)
@then("the statistics should include workflow counts")
def step_check_workflow_statistics(context):
"""Check workflow statistics."""
stats = context.workflow_results["statistics"]
assert "total_workflows" in stats
assert stats["total_workflows"] > 0
assert "workflows_per_category" in stats
assert "total_go_components" in stats
assert "total_python_modules" in stats
@then("the matrix should map Go components to Python modules")
def step_check_go_to_python_mapping(context):
"""Check Go to Python mapping in matrix."""
assert "go_to_python" in context.parity_matrix
assert len(context.parity_matrix["go_to_python"]) > 0
@then("the matrix should identify coverage gaps")
def step_check_coverage_gaps(context):
"""Check that coverage gaps are identified."""
assert "coverage_gaps" in context.parity_matrix
# Coverage gaps may be empty if all tests are defined
@then("the matrix should provide implementation order")
def step_check_implementation_order(context):
"""Check implementation order in matrix."""
assert "implementation_order" in context.parity_matrix
assert len(context.parity_matrix["implementation_order"]) > 0
@then("the implementation order should respect dependencies")
def step_check_dependency_order(context):
"""Check that implementation order respects dependencies."""
order = context.parity_matrix["implementation_order"]
workflows = context.workflow_results["workflows"]
# Basic check - auth workflows should come before workflows that depend on them
auth_index = -1
for i, wf_id in enumerate(order):
if workflows.get(wf_id, {}).get("category") == "authentication":
auth_index = i
break
# Check that workflows depending on auth come after
for i, wf_id in enumerate(order):
wf = workflows.get(wf_id, {})
if "authentication" in wf.get("dependencies", []):
assert i > auth_index or auth_index == -1, (
f"{wf_id} should come after auth workflows"
)
@then("a JSON file should be created with workflow data")
def step_check_json_file(context):
"""Check JSON file creation."""
assert context.json_file.exists()
with open(context.json_file) as f:
data = json.load(f)
assert "workflows" in data
assert "matrix" in data
@then("a YAML file should be created with workflow data")
def step_check_yaml_file(context):
"""Check YAML file creation."""
assert context.yaml_file.exists()
@then("a Markdown documentation should be generated")
def step_check_markdown_doc(context):
"""Check Markdown documentation."""
md_file = context.json_file.parent / "workflow_parity.md"
assert md_file.exists()
content = md_file.read_text()
assert "# Workflow Parity Matrix" in content
@then("the documentation should include all workflows by category")
def step_check_doc_categories(context):
"""Check documentation includes categories."""
md_file = context.json_file.parent / "workflow_parity.md"
content = md_file.read_text()
for category in context.workflow_results["categories"]:
category_title = category.replace("_", " ").title()
assert category_title in content
@then("I should find {workflow_id} workflow")
def step_find_workflow(context, workflow_id):
"""Check that a specific workflow exists."""
# Try to find the workflow in the appropriate context attribute
if hasattr(context, "plan_workflows") and workflow_id in context.plan_workflows:
return
if (
hasattr(context, "context_workflows")
and workflow_id in context.context_workflows
):
return
if hasattr(context, "exec_workflows") and workflow_id in context.exec_workflows:
return
# If not found in any specific category, check all workflows
if hasattr(context, "workflow_extractor"):
workflows = context.workflow_extractor.workflows
assert workflow_id in workflows, f"Workflow {workflow_id} not found"
else:
raise AssertionError(f"Workflow {workflow_id} not found in any category")
@then("each workflow should have stages defined")
def step_check_workflow_stages(context):
"""Check that workflows have stages."""
workflow_collections = []
# Add only the workflow collections that exist
if hasattr(context, "plan_workflows"):
workflow_collections.append(context.plan_workflows)
if hasattr(context, "context_workflows"):
workflow_collections.append(context.context_workflows)
if hasattr(context, "exec_workflows"):
workflow_collections.append(context.exec_workflows)
for workflows in workflow_collections:
if workflows:
for wf_id, workflow in workflows.items():
assert "stages" in workflow, f"No stages in {wf_id}"
assert len(workflow["stages"]) > 0, f"Empty stages in {wf_id}"
@then("each workflow should have test coverage specified")
def step_check_test_coverage(context):
"""Check test coverage specification."""
for workflows in [context.plan_workflows]:
for wf_id, workflow in workflows.items():
assert "test_coverage" in workflow, f"No test_coverage in {wf_id}"
@then("the workflows should include heuristics information")
def step_check_heuristics_info(context):
"""Check for heuristics information."""
auto_context = context.context_workflows.get("context_auto")
assert auto_context is not None
assert "heuristics" in auto_context.get("notes", "").lower() or any(
"heuristics" in stage["name"].lower()
for stage in auto_context.get("stages", [])
)
@then("the workflows should include retry logic details")
def step_check_retry_logic(context):
"""Check for retry logic details."""
auto_debug = context.exec_workflows.get("auto_debug")
assert auto_debug is not None
assert "retry" in auto_debug.get("notes", "").lower() or "retry" in str(
auto_debug.get("dependencies", [])
)
@then("the statistics should include total workflows")
def step_check_total_workflows(context):
"""Check total workflows statistic."""
stats = context.workflow_results["statistics"]
assert stats["total_workflows"] > 0
@then("the statistics should include workflows per category")
def step_check_workflows_per_category(context):
"""Check workflows per category statistic."""
stats = context.workflow_results["statistics"]
assert len(stats["workflows_per_category"]) > 0
@then("the statistics should include total Go components")
def step_check_total_go_components(context):
"""Check total Go components statistic."""
stats = context.workflow_results["statistics"]
assert stats["total_go_components"] > 0
@then("the statistics should include total Python modules")
def step_check_total_python_modules(context):
"""Check total Python modules statistic."""
stats = context.workflow_results["statistics"]
assert stats["total_python_modules"] > 0
@then("the statistics should include test coverage metrics")
def step_check_test_coverage_metrics(context):
"""Check test coverage metrics."""
stats = context.workflow_results["statistics"]
assert "test_coverage" in stats
assert "with_behave" in stats["test_coverage"]
assert "with_robot" in stats["test_coverage"]