UAT: agents resource remove refuses to remove resources with DAG edges — no --force option provided, making removal of linked resources impossible #2407

Open
opened 2026-04-03 17:35:27 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/resource-remove-force-flag-dag-edges
  • Commit Message: fix(cli): add --force flag to agents resource remove to cascade-delete DAG edges
  • Milestone: v3.6.0
  • Parent Epic: #398

Bug Report

What Was Tested

The agents resource remove CLI command when a resource has parent or child DAG edges.

Expected Behavior (from spec)

The spec says agents resource remove <NAME> should remove a resource from the registry. There is no documented restriction preventing removal of resources that have DAG edges. Users should be able to remove resources, with either automatic cascade or a --force flag.

Actual Behavior

In src/cleveragents/cli/commands/resource.py, the resource_remove() function checks for DAG edges and hard-blocks removal if any exist:

edge_count: int = (
    session.query(ResourceEdgeModel)
    .filter(
        (ResourceEdgeModel.parent_id == res.resource_id)
        | (ResourceEdgeModel.child_id == res.resource_id)
    )
    .count()
)
if edge_count > 0:
    console.print(
        f"[red]Cannot remove resource '{res.name or res.resource_id}': "
        f"{edge_count} edge(s) still reference it.[/red]"
    )
    raise typer.Abort()

There is no --force flag to override this restriction. The only way to remove a resource with edges is to manually unlink all edges first using agents resource unlink-child for each edge — but this is not documented and is very cumbersome.

Impact

  1. Resources that have been linked as children cannot be removed without first manually unlinking all edges
  2. No --force option to cascade-delete edges and remove the resource
  3. Spec violation — the spec says agents resource remove <NAME> should remove a resource, with no documented edge restriction
  4. Poor UX — users get a cryptic error with no guidance on how to proceed

Steps to Reproduce

# Add two resources
agents resource add git-checkout local/parent --path /tmp/parent
agents resource add fs-directory local/child --path /tmp/child

# Link them
agents resource link-child local/parent local/child

# Try to remove the child
agents resource remove local/child --yes
# Expected: resource removed (possibly with cascade or --force option)
# Actual: "Cannot remove resource 'local/child': 1 edge(s) still reference it." + abort

Code Location

  • src/cleveragents/cli/commands/resource.pyresource_remove() function (~line 680)

Subtasks

  • Add --force / -f flag to resource_remove() in src/cleveragents/cli/commands/resource.py
  • When --force is passed and edge(s) exist, cascade-delete all ResourceEdgeModel rows referencing the resource (both as parent_id and child_id) before deleting the resource itself
  • Update the error message when edges exist and --force is NOT passed to inform the user they can use --force to cascade-delete edges, or manually unlink with agents resource unlink-child
  • Add remove_resource_with_edges(resource_id) method (or equivalent) to ResourceRegistryService with full static typing
  • Ensure the cascade deletion is wrapped in a single DB transaction — either all edges and the resource are deleted, or none are
  • Tests (Behave): Add scenario for agents resource remove --force on a resource with parent edges — edges and resource are removed
  • Tests (Behave): Add scenario for agents resource remove --force on a resource with child edges — edges and resource are removed
  • Tests (Behave): Add scenario for agents resource remove --force on a resource with both parent and child edges — all edges and resource are removed
  • Tests (Behave): Add scenario for agents resource remove (no --force) on a resource with edges — command aborts with improved error message mentioning --force
  • Tests (Behave): Add @tdd_expected_fail tagged scenario capturing the current hard-block behaviour before the fix
  • Tests (Robot): Add integration test for agents resource remove --force end-to-end with linked resources
  • Verify nox -e typecheck passes (full static typing on all new/modified code)
  • Verify nox -e coverage_report shows coverage >= 97%
  • Run nox (all default sessions), fix any errors

Definition of Done

  • All subtasks above are completed and checked off
  • agents resource remove --force <NAME> successfully removes a resource and all its DAG edges in a single atomic transaction
  • agents resource remove <NAME> (without --force) on a resource with edges aborts with a clear, actionable error message that mentions --force and agents resource unlink-child as remediation options
  • All new code paths are covered by Behave unit tests
  • Integration test covers the end-to-end --force flow via Robot Framework
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/resource-remove-force-flag-dag-edges` - **Commit Message**: `fix(cli): add --force flag to agents resource remove to cascade-delete DAG edges` - **Milestone**: v3.6.0 - **Parent Epic**: #398 ## Bug Report ### What Was Tested The `agents resource remove` CLI command when a resource has parent or child DAG edges. ### Expected Behavior (from spec) The spec says `agents resource remove <NAME>` should remove a resource from the registry. There is no documented restriction preventing removal of resources that have DAG edges. Users should be able to remove resources, with either automatic cascade or a `--force` flag. ### Actual Behavior In `src/cleveragents/cli/commands/resource.py`, the `resource_remove()` function checks for DAG edges and hard-blocks removal if any exist: ```python edge_count: int = ( session.query(ResourceEdgeModel) .filter( (ResourceEdgeModel.parent_id == res.resource_id) | (ResourceEdgeModel.child_id == res.resource_id) ) .count() ) if edge_count > 0: console.print( f"[red]Cannot remove resource '{res.name or res.resource_id}': " f"{edge_count} edge(s) still reference it.[/red]" ) raise typer.Abort() ``` There is **no `--force` flag** to override this restriction. The only way to remove a resource with edges is to manually unlink all edges first using `agents resource unlink-child` for each edge — but this is not documented and is very cumbersome. ### Impact 1. **Resources that have been linked as children cannot be removed** without first manually unlinking all edges 2. **No `--force` option** to cascade-delete edges and remove the resource 3. **Spec violation** — the spec says `agents resource remove <NAME>` should remove a resource, with no documented edge restriction 4. **Poor UX** — users get a cryptic error with no guidance on how to proceed ### Steps to Reproduce ```bash # Add two resources agents resource add git-checkout local/parent --path /tmp/parent agents resource add fs-directory local/child --path /tmp/child # Link them agents resource link-child local/parent local/child # Try to remove the child agents resource remove local/child --yes # Expected: resource removed (possibly with cascade or --force option) # Actual: "Cannot remove resource 'local/child': 1 edge(s) still reference it." + abort ``` ### Code Location - `src/cleveragents/cli/commands/resource.py` — `resource_remove()` function (~line 680) ## Subtasks - [ ] Add `--force` / `-f` flag to `resource_remove()` in `src/cleveragents/cli/commands/resource.py` - [ ] When `--force` is passed and edge(s) exist, cascade-delete all `ResourceEdgeModel` rows referencing the resource (both as `parent_id` and `child_id`) before deleting the resource itself - [ ] Update the error message when edges exist and `--force` is NOT passed to inform the user they can use `--force` to cascade-delete edges, or manually unlink with `agents resource unlink-child` - [ ] Add `remove_resource_with_edges(resource_id)` method (or equivalent) to `ResourceRegistryService` with full static typing - [ ] Ensure the cascade deletion is wrapped in a single DB transaction — either all edges and the resource are deleted, or none are - [ ] Tests (Behave): Add scenario for `agents resource remove --force` on a resource with parent edges — edges and resource are removed - [ ] Tests (Behave): Add scenario for `agents resource remove --force` on a resource with child edges — edges and resource are removed - [ ] Tests (Behave): Add scenario for `agents resource remove --force` on a resource with both parent and child edges — all edges and resource are removed - [ ] Tests (Behave): Add scenario for `agents resource remove` (no `--force`) on a resource with edges — command aborts with improved error message mentioning `--force` - [ ] Tests (Behave): Add `@tdd_expected_fail` tagged scenario capturing the current hard-block behaviour before the fix - [ ] Tests (Robot): Add integration test for `agents resource remove --force` end-to-end with linked resources - [ ] Verify `nox -e typecheck` passes (full static typing on all new/modified code) - [ ] Verify `nox -e coverage_report` shows coverage >= 97% - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done - [ ] All subtasks above are completed and checked off - [ ] `agents resource remove --force <NAME>` successfully removes a resource and all its DAG edges in a single atomic transaction - [ ] `agents resource remove <NAME>` (without `--force`) on a resource with edges aborts with a clear, actionable error message that mentions `--force` and `agents resource unlink-child` as remediation options - [ ] All new code paths are covered by Behave unit tests - [ ] Integration test covers the end-to-end `--force` flow via Robot Framework - [ ] A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation - [ ] The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly - [ ] The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.6.0 milestone 2026-04-03 17:35:32 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Medium — Missing --force flag on agents resource remove makes it impossible to remove resources with DAG edges. This is a usability gap.
  • Milestone: v3.6.0
  • MoSCoW: Should Have — Users need to be able to remove linked resources. The workaround (manually removing edges first) is cumbersome but possible.
  • Parent Epic: #398 (Post-MVP Resources)

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

Issue triaged by project owner: - **State**: Verified - **Priority**: Medium — Missing `--force` flag on `agents resource remove` makes it impossible to remove resources with DAG edges. This is a usability gap. - **Milestone**: v3.6.0 - **MoSCoW**: Should Have — Users need to be able to remove linked resources. The workaround (manually removing edges first) is cumbersome but possible. - **Parent Epic**: #398 (Post-MVP Resources) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
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.

Blocks
#398 Epic: Post-MVP Resources
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#2407
No description provided.