UAT: Non-local namespace resolution to default server not implemented in NamespacedName.parse() #4889

Open
opened 2026-04-08 20:15:51 +00:00 by HAL9000 · 2 comments
Owner

Bug Report

Feature Area: Namespacing — Namespace Resolution in Local vs Server Mode
Tested by: UAT tester instance uat-namespacing

What Was Tested

Code analysis of namespace resolution logic across src/cleveragents/domain/models/core/plan.py, src/cleveragents/domain/models/core/project.py, and src/cleveragents/application/services/permission_service.py.

Expected Behavior (from spec)

Per ADR-002 (Namespace System), Resolution Rules:

  1. If the server prefix is omitted, the default server is assumed — unless the namespace is local, which always resolves locally.

And from the spec glossary:

Namespace: The scoping segment in the name format [[server:]namespace/]name. Defaults to local/ when omitted. local/ is reserved for local-only items. Non-local/ namespaces with server omitted assume the default configured server.

This means:

  • local/my-action → resolves locally (no server)
  • freemo/my-action → resolves to <default_server>:freemo/my-action
  • cleverthis/my-action → resolves to <default_server>:cleverthis/my-action
  • prod:freemo/my-action → resolves to prod server explicitly

Actual Behavior

NamespacedName.parse() in plan.py simply stores the namespace as-is with no server resolution:

@classmethod
def parse(cls, full_name: str) -> NamespacedName:
    server = None
    namespace = "local"
    name = full_name

    if ":" in name:
        server, name = name.split(":", 1)

    if "/" in name:
        namespace, name = name.split("/", 1)

    return cls(server=server, namespace=namespace, name=name)
    # ↑ server remains None for "freemo/my-action" — no default server resolution

When freemo/my-action is parsed, server=None is stored. There is no subsequent step that resolves server=None + namespace="freemo" to server=<default_configured_server>.

The ParsedName.is_remote property in project.py correctly identifies non-local as remote, but this is only a classification — it does not perform actual server resolution.

The permission_service.py is_local_mode() check is a runtime mode check, not a namespace resolution step.

Code Location

  • src/cleveragents/domain/models/core/plan.py, lines 238–261 (NamespacedName.parse())
  • src/cleveragents/domain/models/core/project.py, lines 99–110 (ParsedName.is_remote)
  • src/cleveragents/application/services/config_service.py, lines 303–311 (server.namespace config key)
  • No namespace resolver service exists in src/cleveragents/application/services/

Impact

  • When a user creates an action with freemo/my-action (intending it to be on the default server), the system stores server=None — it cannot distinguish between "no server specified yet" and "explicitly local"
  • In server mode, looking up freemo/my-action would need to know which server to query, but this information is lost at parse time
  • The server.namespace config key (CLEVERAGENTS_SERVER_NAMESPACE) exists but is never used during name resolution

Expected Fix

A NamespaceResolver service should be introduced (or the existing NamespacedName.parse() should accept an optional default_server parameter) that:

  1. Parses the raw name string
  2. If server is None and namespace != "local", sets server to the configured default server
  3. Returns the fully resolved NamespacedName

This resolver should be called at the application service layer (e.g., in PlanLifecycleService, ProjectService) rather than at the domain model layer, to keep the domain model pure.


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area:** Namespacing — Namespace Resolution in Local vs Server Mode **Tested by:** UAT tester instance `uat-namespacing` ### What Was Tested Code analysis of namespace resolution logic across `src/cleveragents/domain/models/core/plan.py`, `src/cleveragents/domain/models/core/project.py`, and `src/cleveragents/application/services/permission_service.py`. ### Expected Behavior (from spec) Per ADR-002 (Namespace System), Resolution Rules: > 1. If the server prefix is omitted, the **default server is assumed** — unless the namespace is `local`, which always resolves locally. And from the spec glossary: > **Namespace**: The scoping segment in the name format `[[server:]namespace/]name`. Defaults to `local/` when omitted. `local/` is reserved for local-only items. **Non-`local/` namespaces with server omitted assume the default configured server.** This means: - `local/my-action` → resolves locally (no server) - `freemo/my-action` → resolves to `<default_server>:freemo/my-action` - `cleverthis/my-action` → resolves to `<default_server>:cleverthis/my-action` - `prod:freemo/my-action` → resolves to `prod` server explicitly ### Actual Behavior `NamespacedName.parse()` in `plan.py` simply stores the namespace as-is with no server resolution: ```python @classmethod def parse(cls, full_name: str) -> NamespacedName: server = None namespace = "local" name = full_name if ":" in name: server, name = name.split(":", 1) if "/" in name: namespace, name = name.split("/", 1) return cls(server=server, namespace=namespace, name=name) # ↑ server remains None for "freemo/my-action" — no default server resolution ``` When `freemo/my-action` is parsed, `server=None` is stored. There is no subsequent step that resolves `server=None` + `namespace="freemo"` to `server=<default_configured_server>`. The `ParsedName.is_remote` property in `project.py` correctly identifies non-local as remote, but this is only a classification — it does not perform actual server resolution. The `permission_service.py` `is_local_mode()` check is a runtime mode check, not a namespace resolution step. ### Code Location - `src/cleveragents/domain/models/core/plan.py`, lines 238–261 (`NamespacedName.parse()`) - `src/cleveragents/domain/models/core/project.py`, lines 99–110 (`ParsedName.is_remote`) - `src/cleveragents/application/services/config_service.py`, lines 303–311 (`server.namespace` config key) - No namespace resolver service exists in `src/cleveragents/application/services/` ### Impact - When a user creates an action with `freemo/my-action` (intending it to be on the default server), the system stores `server=None` — it cannot distinguish between "no server specified yet" and "explicitly local" - In server mode, looking up `freemo/my-action` would need to know which server to query, but this information is lost at parse time - The `server.namespace` config key (`CLEVERAGENTS_SERVER_NAMESPACE`) exists but is never used during name resolution ### Expected Fix A `NamespaceResolver` service should be introduced (or the existing `NamespacedName.parse()` should accept an optional `default_server` parameter) that: 1. Parses the raw name string 2. If `server is None` and `namespace != "local"`, sets `server` to the configured default server 3. Returns the fully resolved `NamespacedName` This resolver should be called at the application service layer (e.g., in `PlanLifecycleService`, `ProjectService`) rather than at the domain model layer, to keep the domain model pure. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — Non-local namespace resolution not implemented; affects multi-server workflows
  • Milestone: v3.5.0 (Autonomy Hardening — namespacing)
  • Story Points: 3 — M — Implementing server-mode namespace resolution in NamespacedName.parse() is a medium task
  • MoSCoW: Should Have — Non-local namespace resolution is important for multi-server deployments but not blocking local operation
  • Parent Epic: #4947 (Server Implementation Legendary)

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — Non-local namespace resolution not implemented; affects multi-server workflows - **Milestone**: v3.5.0 (Autonomy Hardening — namespacing) - **Story Points**: 3 — M — Implementing server-mode namespace resolution in NamespacedName.parse() is a medium task - **MoSCoW**: Should Have — Non-local namespace resolution is important for multi-server deployments but not blocking local operation - **Parent Epic**: #4947 (Server Implementation Legendary) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
freemo added this to the v3.5.0 milestone 2026-04-08 23:40:56 +00:00
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — agents plan execute missing --dry-run flag
  • Milestone: v3.5.0 — Plan execution dry-run is M6 scope
  • Story Points: 3 — M — Adding --dry-run flag to plan execute command
  • MoSCoW: Should Have — Dry-run is important for safe plan execution but not blocking core workflow
  • Parent Epic: #360 (Autonomy Hardening + Stubs M6)

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — `agents plan execute` missing `--dry-run` flag - **Milestone**: v3.5.0 — Plan execution dry-run is M6 scope - **Story Points**: 3 — M — Adding `--dry-run` flag to plan execute command - **MoSCoW**: Should Have — Dry-run is important for safe plan execution but not blocking core workflow - **Parent Epic**: #360 (Autonomy Hardening + Stubs M6) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#4889
No description provided.