From 7cf03f03f4245093388fa923ef1c6d5c361a4650 Mon Sep 17 00:00:00 2001 From: CoreRasurae Date: Tue, 24 Mar 2026 20:16:56 +0000 Subject: [PATCH 1/2] fix(action): query persisted actions from database in list_actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit list_actions() previously merged in-memory cache with the database but used the cache as the primary source. Actions created by previous CLI invocations were only stored in the database and were invisible to the current process. When persistence is enabled and a Unit of Work is available, the method now queries the database first — using get_by_namespace() when a namespace filter is given, or the new list_all() otherwise — and refreshes the in-memory cache with any newly-discovered entries. Falls back to the in-memory cache on DatabaseError or when no UoW is wired. Added ActionRepository.list_all() to retrieve all persisted actions ordered by namespace and name. Refs: #760 --- CHANGELOG.md | 5 +++ .../services/plan_lifecycle_service.py | 31 +++++++++++++++++-- .../infrastructure/database/repositories.py | 21 +++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9322402b1..66630d6f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -136,6 +136,11 @@ non-serialisable config blobs (without exposing serializer internals in user-facing errors). Comprehensive BDD and Robot Framework tests cover all resolution paths and edge cases. (#901) +- Fixed `list_actions()` to query the database when persistence is enabled + so that actions created by previous CLI invocations are visible. Falls + back to the in-memory cache on database errors or when no Unit of Work + is wired. Added `ActionRepository.list_all()` for unfiltered action + listing. (#760) - Added BuiltinAdapter class and MCP automatic resource slot creation. BuiltinAdapter wraps register_file_tools/register_git_tools/register_subplan_tool into a unified adapter interface. McpAdapter.infer_resource_slots() analyzes diff --git a/src/cleveragents/application/services/plan_lifecycle_service.py b/src/cleveragents/application/services/plan_lifecycle_service.py index 7e3528fea..7300ae555 100644 --- a/src/cleveragents/application/services/plan_lifecycle_service.py +++ b/src/cleveragents/application/services/plan_lifecycle_service.py @@ -622,8 +622,10 @@ class PlanLifecycleService: ) -> list[Action]: """List actions with optional filtering. - When persistence is enabled, results are merged from the in-memory - cache and the database layer. + When persistence is enabled, results are queried from the database + so that actions created by previous CLI invocations are visible. + Falls back to the in-memory cache on DB errors or when no UoW is + wired. Args: namespace: Filter by namespace @@ -632,6 +634,31 @@ class PlanLifecycleService: Returns: List of matching Actions """ + # Query the database when persistence is enabled so that actions + # created by previous CLI invocations are visible. + if self._persisted and self.unit_of_work is not None: + try: + with self.unit_of_work.transaction() as ctx: + if namespace: + state_str = state.value if state else None + actions = ctx.actions.get_by_namespace( + namespace, state=state_str + ) + else: + actions = ctx.actions.list_all() + # Refresh the in-memory cache with persisted actions. + for a in actions: + key = str(a.namespaced_name) + if key not in self._actions: + self._actions[key] = a + # Apply state filter when list_all was used (no namespace). + if state and not namespace: + actions = [a for a in actions if a.state == state] + return actions + except DatabaseError: + logger.debug("DB action list failed, falling back to in-memory cache") + + # In-memory fallback (no persistence or DB error). actions = list(self._actions.values()) if namespace: diff --git a/src/cleveragents/infrastructure/database/repositories.py b/src/cleveragents/infrastructure/database/repositories.py index 1f537651e..cf17c1819 100644 --- a/src/cleveragents/infrastructure/database/repositories.py +++ b/src/cleveragents/infrastructure/database/repositories.py @@ -980,6 +980,27 @@ class ActionRepository: f"Failed to list actions in namespace '{namespace}': {exc}" ) from exc + @database_retry + def list_all(self) -> list[Any]: + """List all persisted actions, ordered by namespace then name. + + Returns: + List of ``Action`` domain objects. + """ + session = self._session() + try: + rows = ( + session.query(LifecycleActionModel) + .order_by( + LifecycleActionModel.namespace, + LifecycleActionModel.name, + ) + .all() + ) + return [row.to_domain() for row in rows] + except (OperationalError, SQLAlchemyDatabaseError) as exc: + raise DatabaseError(f"Failed to list all actions: {exc}") from exc + @database_retry def get_by_state(self, state: str) -> list[Any]: """List actions by state, ordered by ``updated_at`` DESC. -- 2.52.0 From d2c70bd48918abec26d2f22c18757e21e4aa012f Mon Sep 17 00:00:00 2001 From: CoreRasurae Date: Fri, 13 Mar 2026 01:31:38 +0000 Subject: [PATCH 2/2] =?UTF-8?q?test(e2e):=20workflow=20example=2014=20?= =?UTF-8?q?=E2=80=94=20server=20mode=20team=20collaboration=20(supervised?= =?UTF-8?q?=20profile)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented Robot Framework E2E test suite validating Specification Workflow Example 14 (Server Mode Team Collaboration). Tests exercise the real CleverAgents CLI with zero mocking, covering server mode configuration (server.url, server.token, core.namespace), diagnostics, action publishing to team namespace with namespace-scoped listing, actor registration, plan list graceful handling, and supervised automation profile verification. Review fixes applied: - Added WF14 Suite Setup with agents init and uuid4 suffix generation - Added WF14 Suite Teardown to reset config state (server.url, server.token, core.namespace) - Added server.token config round-trip per spec Example 14 Step 1 - Changed action name to myteam/ namespace prefix per spec Step 2 - Added action list --namespace myteam test per issue AC - Replaced epoch-based name uniqueness with uuid4 for CI safety - Updated diagnostics test documentation (no server connectivity check) - Changed to Force Tags E2E at suite level for consistency - Added description field to actor YAML configuration - Updated plan list test documentation to reflect actual behavior - Reverted unrelated cls->klass rename from strategy_registry.py (CONTRIBUTING.md: do not mix cosmetic changes with functional changes) - Updated CHANGELOG to accurately reflect test coverage ISSUES CLOSED: #760 --- CHANGELOG.md | 6 ++ robot/e2e/wf14_server_mode.robot | 135 +++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 robot/e2e/wf14_server_mode.robot diff --git a/CHANGELOG.md b/CHANGELOG.md index 66630d6f9..707a2dec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -493,6 +493,12 @@ Framework variables. (`robot/e2e/wf07_cicd.robot`, `robot/e2e/common_e2e.resource`, `robot/common_vars.py`) (#753) +- Added E2E Robot Framework test for Specification Workflow Example 14: Server + Mode — Team Collaboration. Exercises server mode configuration (server URL, + token, namespace), diagnostics, action publishing to team namespace with + namespace-scoped listing, actor registration, plan list smoke test, and + `supervised` automation profile verification with threshold field assertions + via real CLI with zero mocking. (`robot/e2e/wf14_server_mode.robot`) (#760) - Fixed `agents session list`, `agents session create`, and other session subcommands raising `AttributeError: 'DynamicContainer' object has no attribute 'db'` after `agents init`. Root cause: `_get_session_service()` diff --git a/robot/e2e/wf14_server_mode.robot b/robot/e2e/wf14_server_mode.robot new file mode 100644 index 000000000..a1aef8acd --- /dev/null +++ b/robot/e2e/wf14_server_mode.robot @@ -0,0 +1,135 @@ +*** Settings *** +Documentation E2E test for Workflow Example 14: server mode team collaboration. +... +... Validates the ``supervised`` automation profile in a distributed +... team scenario where multiple engineers share actions, actors, and +... projects via CleverAgents server mode. All commands exercise the +... real CLI with zero mocking. +... +... Coverage: Steps 1–2 (server config, resource publishing). +... Steps 3–4 (multi-machine usage, team monitoring) require a +... live server and are deferred. +Resource common_e2e.resource +Suite Setup WF14 Suite Setup +Suite Teardown WF14 Suite Teardown +Force Tags E2E + +*** Keywords *** +WF14 Suite Setup + [Documentation] E2E Suite Setup plus database initialisation for WF14 tests. + E2E Suite Setup + # Initialise the database so action/actor/plan commands work in all tests. + ${init}= Run CleverAgents Command init --yes + Should Be Equal As Integers ${init.rc} 0 + # Generate a unique suffix for entity names to avoid UNIQUE + # constraint collisions on repeated E2E runs or parallel CI. + ${suffix}= Evaluate __import__('uuid').uuid4().hex[:12] + Set Suite Variable ${RUN_SUFFIX} ${suffix} + +WF14 Suite Teardown + [Documentation] Restore config state and clean up E2E test environment. + # Reset config keys set during the server config test to avoid + # contaminating subsequent test suites. + Run Keyword And Ignore Error Run CleverAgents Command config set server.url ${EMPTY} expected_rc=None + Run Keyword And Ignore Error Run CleverAgents Command config set server.token ${EMPTY} expected_rc=None + Run Keyword And Ignore Error Run CleverAgents Command config set core.namespace local expected_rc=None + E2E Suite Teardown + +*** Test Cases *** +WF14 E2E Server Config Setup + [Documentation] Configure server URL, authentication token, and team namespace + ... for server mode per Specification Example 14 Step 1. + # Set and verify server URL + ${set_url}= Run CleverAgents Command config set server.url https://agents.example.com + Output Should Contain ${set_url} server.url + ${get_url}= Run CleverAgents Command config get server.url + Output Should Contain ${get_url} https://agents.example.com + # Set and verify server token (spec Step 1 includes token configuration) + ${set_token}= Run CleverAgents Command config set server.token tok_e2e_test_placeholder + Output Should Contain ${set_token} server.token + ${get_token}= Run CleverAgents Command config get server.token + Output Should Contain ${get_token} tok_e2e_test_placeholder + # Set and verify team namespace + ${set_ns}= Run CleverAgents Command config set core.namespace myteam + Output Should Contain ${set_ns} core.namespace + ${get_ns}= Run CleverAgents Command config get core.namespace + Output Should Contain ${get_ns} myteam + +WF14 E2E Diagnostics + [Documentation] Run diagnostics and verify basic health-check output. + ... Diagnostics checks are all local (config, database, disk, + ... API keys, git, etc.) so the command should succeed even + ... without a live server. Server-mode diagnostics (Server + ... connectivity, Namespace membership) shown in the spec are + ... not yet implemented in the diagnostics command (spec gap). + ${result}= Run CleverAgents Command diagnostics --format plain expected_rc=0 + # Basic diagnostic categories should appear in the output + ${combined}= Set Variable ${result.stdout}\n${result.stderr} + Should Contain Any ${combined} config Config configuration + Should Contain Any ${combined} database Database db + Should Contain Any ${combined} disk Disk space storage + +WF14 E2E Action Create For Namespace + [Documentation] Create an action in the team namespace and verify it persists. + ... Uses ``myteam/`` prefix per Specification Example 14 Step 2. + ${action_name}= Set Variable myteam/gen-tests-${RUN_SUFFIX} + ${yaml_content}= Catenate SEPARATOR=\n + ... name: ${action_name} + ... description: Generate unit tests for source modules + ... strategy_actor: local/strategist + ... execution_actor: local/executor + ... definition_of_done: All source modules have corresponding unit tests. + ... reusable: true + ... read_only: true + ${yaml_file}= Set Variable ${SUITE_HOME}${/}generate-tests-action.yaml + Create File ${yaml_file} ${yaml_content} + ${create_result}= Run CleverAgents Command action create --config ${yaml_file} + Output Should Contain ${create_result} gen-tests + # Verify action persists across separate CLI invocations via action show + ${show_result}= Run CleverAgents Command action show ${action_name} + Output Should Contain ${show_result} gen-tests + # Make the action name available for the namespace listing test + Set Suite Variable ${WF14_ACTION_NAME} ${action_name} + +WF14 E2E Action List By Namespace + [Documentation] List shared actions filtered by team namespace. + ... Validates Specification Example 14 Step 2: + ... ``agents action list --namespace myteam``. + ${list_result}= Run CleverAgents Command action list --namespace myteam --format plain + Output Should Contain ${list_result} gen-tests + +WF14 E2E Actor Add For Namespace + [Documentation] Add an actor from YAML configuration and verify it appears. + ... Custom actors must use the ``local/`` namespace prefix per + ... the current ActorService validation. + ${actor_name}= Set Variable local/team-rev-${RUN_SUFFIX} + ${yaml_content}= Catenate SEPARATOR=\n + ... provider: openai + ... model: gpt-4 + ... description: Team code reviewer actor for collaborative reviews + ${yaml_file}= Set Variable ${SUITE_HOME}${/}team-reviewer-actor.yaml + Create File ${yaml_file} ${yaml_content} + ${add_result}= Run CleverAgents Command actor add ${actor_name} --config ${yaml_file} + Output Should Contain ${add_result} team-rev + # Use --format plain to avoid table truncation + ${list_result}= Run CleverAgents Command actor list --format plain + Output Should Contain ${list_result} team-rev + +WF14 E2E Plan List + [Documentation] Verify that the plan list command executes without crashing. + ... No plans exist after init, so the output may be an empty table + ... or an informational message. The ``--namespace`` flag is not + ... yet implemented for plan list (spec gap). + ${result}= Run CleverAgents Command plan list expected_rc=0 + # After init, plan list should succeed (rc=0) even with an empty plan table + Should Not Be Empty ${result.stdout}${result.stderr} + +WF14 E2E Supervised Profile Verification + [Documentation] Verify the built-in supervised automation profile exists and + ... contains the expected confidence threshold fields. + ${result}= Run CleverAgents Command automation-profile show supervised + Output Should Contain ${result} supervised + # Verify supervised-specific threshold fields are present in the output + Output Should Contain ${result} auto_strategize + Output Should Contain ${result} auto_execute + Output Should Contain ${result} auto_apply -- 2.52.0