"""WF02 lifecycle-level utility helpers.""" from __future__ import annotations from collections.abc import Callable from cleveragents.application.services.plan_execution_context import ( PlanExecutionContext, ) from cleveragents.domain.models.core.change import ( ChangeEntry, ChangeOperation, InMemoryChangeSetStore, ) def record_files_via_execution_context( plan_id: str, store: InMemoryChangeSetStore, files: dict[str, str], ) -> str: """Record file artifacts through PlanExecutionContext lifecycle APIs.""" execution_context = PlanExecutionContext( plan_id=plan_id, automation_profile="trusted", changeset_store=store, ) changeset_id = execution_context.start_changeset() for index, rel_path in enumerate(sorted(files), start=1): execution_context.record_change( ChangeEntry( plan_id=plan_id, resource_id=f"wf02-res-{index}", tool_name="builtin/file-write", operation=ChangeOperation.CREATE, path=rel_path, after_hash=f"wf02hash{index}", ) ) return changeset_id def assert_rejected_generated_path( validator: Callable[[str], object], rel_path: str, expected_error_substring: str, ) -> None: """Assert the path safety guard rejects a path with expected reason.""" try: validator(rel_path) except AssertionError as exc: message = str(exc) assert expected_error_substring in message, ( f"Expected '{expected_error_substring}' in '{message}'" ) else: raise AssertionError(f"Expected path rejection for: {rel_path}")