BUG-HUNT: [consistency] Duplicate context sub-typer registration on actor.app silently shadows actor_context_app, making agents actor context remove --all unreachable #6419

Open
opened 2026-04-09 21:02:02 +00:00 by HAL9000 · 0 comments
Owner

Bug Report: [consistency] — Duplicate Typer Sub-App Registration Shadows actor_context_app Commands

Severity Assessment

  • Impact: agents actor context remove --all (bulk removal of named actor contexts) is completely unreachable. Users invoking agents actor context remove --all get the wrong remove command that expects file path arguments, causing a confusing "Missing argument 'PATHS'" error instead of bulk context removal.
  • Likelihood: High — any user following the spec for bulk context removal will hit this immediately.
  • Priority: High

Location

  • File: src/cleveragents/cli/commands/actor.py (line 966) and src/cleveragents/cli/main.py (lines 116–121)
  • Function/Class: _register_subcommands() in main.py; module-level app.add_typer(...) in actor.py
  • Lines: actor.py:966, main.py:116–121

Description

actor.app ends up with two different Typer sub-apps both registered under the name "context":

  1. First registration (at actor.py module-import time, line 966):

    app.add_typer(actor_context_app, name="context")
    

    actor_context_app (from actor_context.py) provides the actor-scoped context management commands:

    • remove — with --all/-a and --yes/-y flags for bulk removal of named contexts
    • export — exports a named context to JSON/YAML
    • import — imports a named context from JSON/YAML
  2. Second registration (inside main._register_subcommands(), line 116–121):

    actor.app.add_typer(
        context.app,
        name="context",
        help="Actor context management commands",
    )
    

    context.app (from context.py) provides the project-scoped file context management commands:

    • add, load, remove, list, show, export, import, delete, clear
    • remove here takes file path arguments, NOT context names

Empirically verified that when Typer receives two add_typer() calls with the same name, the second registration wins (the first is completely discarded):

>>> click_app = typer.main.get_command(app)
>>> sub_group = click_app.commands['sub']
>>> list(sub_group.commands.keys())
['cmd2']   # Only commands from the SECOND registration survive

Evidence

# actor.py line 966 — FIRST registration (loses)
app.add_typer(actor_context_app, name="context")   # has: remove --all, export, import

# main.py lines 116-121 — SECOND registration (wins, shadows first)
actor.app.add_typer(
    context.app,
    name="context",
    help="Actor context management commands",
)
# context.app has: add, load, remove (paths only), list, show, export, import, delete, clear

The remove command from context.py (which survives) requires path arguments:

@app.command("remove")
def context_remove(
    paths: Annotated[
        list[str],
        typer.Argument(help="Paths to remove from context"),  # ← FILE PATHS, not context names
    ],
) -> None:

The remove command from actor_context.py (which is shadowed/lost) supports --all:

@app.command("remove")
def context_remove(
    name: Annotated[str | None, ...] = None,
    all_contexts: Annotated[bool, typer.Option("--all", "-a", ...)] = False,
    yes: Annotated[bool, typer.Option("--yes", "-y", ...)] = False,
    ...

Expected Behavior

agents actor context remove --all --yes should bulk-remove all named actor contexts.
agents actor context remove docs should remove the named context "docs".

Actual Behavior

The shadowed context.py remove command activates instead. Since it expects file paths as positional arguments:

  • agents actor context remove --all → error: "Missing argument 'PATHS'" (--all is not recognized)
  • agents actor context remove docs → attempts to remove a file named "docs" from the project context, not an actor context

Suggested Fix

Two options:

  1. Remove the module-level add_typer from actor.py line 966 and let main.py's _register_subcommands() be the sole registration point (using the correct context.app). Merge any missing commands from actor_context_app into context.app or vice versa.
  2. Consolidate the two context apps into a single module with all required commands: remove (with --all), export, import, add, list, show, clear, delete.

Category

consistency

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_, and @tdd_expected_fail to prove the bug exists before fixing it.


Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: bug-hunter

## Bug Report: [consistency] — Duplicate Typer Sub-App Registration Shadows actor_context_app Commands ### Severity Assessment - **Impact**: `agents actor context remove --all` (bulk removal of named actor contexts) is completely unreachable. Users invoking `agents actor context remove --all` get the wrong `remove` command that expects file path arguments, causing a confusing "Missing argument 'PATHS'" error instead of bulk context removal. - **Likelihood**: High — any user following the spec for bulk context removal will hit this immediately. - **Priority**: High ### Location - **File**: `src/cleveragents/cli/commands/actor.py` (line 966) and `src/cleveragents/cli/main.py` (lines 116–121) - **Function/Class**: `_register_subcommands()` in `main.py`; module-level `app.add_typer(...)` in `actor.py` - **Lines**: `actor.py:966`, `main.py:116–121` ### Description `actor.app` ends up with **two different Typer sub-apps both registered under the name `"context"`**: 1. **First registration** (at `actor.py` module-import time, line 966): ```python app.add_typer(actor_context_app, name="context") ``` `actor_context_app` (from `actor_context.py`) provides the **actor-scoped** context management commands: - `remove` — with `--all`/`-a` and `--yes`/`-y` flags for bulk removal of **named contexts** - `export` — exports a named context to JSON/YAML - `import` — imports a named context from JSON/YAML 2. **Second registration** (inside `main._register_subcommands()`, line 116–121): ```python actor.app.add_typer( context.app, name="context", help="Actor context management commands", ) ``` `context.app` (from `context.py`) provides the **project-scoped** file context management commands: - `add`, `load`, `remove`, `list`, `show`, `export`, `import`, `delete`, `clear` - `remove` here takes **file path arguments**, NOT context names Empirically verified that when Typer receives two `add_typer()` calls with the same name, the **second registration wins** (the first is completely discarded): ```python >>> click_app = typer.main.get_command(app) >>> sub_group = click_app.commands['sub'] >>> list(sub_group.commands.keys()) ['cmd2'] # Only commands from the SECOND registration survive ``` ### Evidence ```python # actor.py line 966 — FIRST registration (loses) app.add_typer(actor_context_app, name="context") # has: remove --all, export, import # main.py lines 116-121 — SECOND registration (wins, shadows first) actor.app.add_typer( context.app, name="context", help="Actor context management commands", ) # context.app has: add, load, remove (paths only), list, show, export, import, delete, clear ``` The `remove` command from `context.py` (which survives) requires path arguments: ```python @app.command("remove") def context_remove( paths: Annotated[ list[str], typer.Argument(help="Paths to remove from context"), # ← FILE PATHS, not context names ], ) -> None: ``` The `remove` command from `actor_context.py` (which is shadowed/lost) supports `--all`: ```python @app.command("remove") def context_remove( name: Annotated[str | None, ...] = None, all_contexts: Annotated[bool, typer.Option("--all", "-a", ...)] = False, yes: Annotated[bool, typer.Option("--yes", "-y", ...)] = False, ... ``` ### Expected Behavior `agents actor context remove --all --yes` should bulk-remove all named actor contexts. `agents actor context remove docs` should remove the named context "docs". ### Actual Behavior The shadowed `context.py` `remove` command activates instead. Since it expects file paths as positional arguments: - `agents actor context remove --all` → error: "Missing argument 'PATHS'" (--all is not recognized) - `agents actor context remove docs` → attempts to remove a file named "docs" from the project context, not an actor context ### Suggested Fix Two options: 1. **Remove the module-level `add_typer` from `actor.py` line 966** and let `main.py`'s `_register_subcommands()` be the sole registration point (using the correct `context.app`). Merge any missing commands from `actor_context_app` into `context.app` or vice versa. 2. **Consolidate the two context apps** into a single module with all required commands: `remove` (with `--all`), `export`, `import`, `add`, `list`, `show`, `clear`, `delete`. ### Category consistency ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it. --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: bug-hunter
HAL9000 added this to the v3.2.0 milestone 2026-04-09 21:09:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

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