agents resource remove does not check project links before deletion #9092

Open
opened 2026-04-14 07:27:01 +00:00 by HAL9000 · 1 comment
Owner

Metadata

  • Commit Message: fix(resource): enforce project-link guard in agents resource remove
  • Branch: fix/resource-remove-project-link-guard

Background and Context

The specification (docs/specification.md, line 10954) explicitly states:

"Removes a registered resource and all its auto-discovered child resources. A git-checkout resource can have hundreds of child resources (files, directories). This operation fails if the resource is linked to any project — use agents project unlink-resource first."

This is a safety guard to prevent dangling project-resource references when a resource is deleted.

Current Behavior

The agents resource remove command (implemented in src/cleveragents/cli/commands/resource.py, function resource_remove) only checks for DAG edges (parent/child resource links via ResourceEdgeModel) before allowing deletion. It does not check whether the resource is linked to any project via ProjectResourceLinkRepository.

As a result, a resource can be deleted even when it is still linked to one or more projects, leaving dangling references in the project registry. The project's linked_resources list will still reference the now-deleted resource ID, causing potential errors when the project is shown or used.

Relevant code (in resource_remove):

# Check for edges
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 equivalent check for project links.

Expected Behavior

Before deleting a resource, agents resource remove must check whether the resource is linked to any project. If it is, the command must fail with a clear error message such as:

Error: Cannot remove resource 'local/my-repo': it is linked to 1 project(s).
Use 'agents project unlink-resource <project> local/my-repo' first.

The check should query the ProjectResourceLinkRepository (or equivalent) for any links where resource_id matches the resource being deleted.

Acceptance Criteria

  1. agents resource remove <resource> fails with exit code 1 and a descriptive error message when the resource is linked to one or more projects.
  2. The error message names the number of projects the resource is linked to and instructs the user to use agents project unlink-resource first.
  3. agents resource remove <resource> succeeds when the resource is not linked to any project (existing behavior preserved).
  4. A BDD scenario is added to features/resource_cli.feature (or a new feature file) covering the "remove fails when linked to project" case.
  5. All existing tests continue to pass.

Supporting Information

  • Spec reference: docs/specification.md, line 10954 (section "agents resource remove")
  • Implementation: src/cleveragents/cli/commands/resource.py, function resource_remove (around line 1346)
  • Related: src/cleveragents/cli/commands/project.py_get_resource_link_repo() helper already exists and can be reused

Subtasks

  • Add project-link check in resource_remove before the DAG edge check
  • Return a clear error message listing the number of linked projects
  • Tests (Behave): Add scenario "Remove resource linked to project fails" in features/resource_cli.feature
  • Tests (Behave): Add scenario "Remove resource not linked to project succeeds" (regression guard)
  • Run nox (all default sessions), fix any errors
  • Verify coverage >=97% via nox -s coverage_report

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • 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.

Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata - **Commit Message**: `fix(resource): enforce project-link guard in agents resource remove` - **Branch**: `fix/resource-remove-project-link-guard` ## Background and Context The specification (`docs/specification.md`, line 10954) explicitly states: > "Removes a registered resource and all its auto-discovered child resources. A git-checkout resource can have hundreds of child resources (files, directories). **This operation fails if the resource is linked to any project — use `agents project unlink-resource` first.**" This is a safety guard to prevent dangling project-resource references when a resource is deleted. ## Current Behavior The `agents resource remove` command (implemented in `src/cleveragents/cli/commands/resource.py`, function `resource_remove`) only checks for DAG edges (parent/child resource links via `ResourceEdgeModel`) before allowing deletion. It does **not** check whether the resource is linked to any project via `ProjectResourceLinkRepository`. As a result, a resource can be deleted even when it is still linked to one or more projects, leaving dangling references in the project registry. The project's `linked_resources` list will still reference the now-deleted resource ID, causing potential errors when the project is shown or used. Relevant code (in `resource_remove`): ```python # Check for edges 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 equivalent check for project links. ## Expected Behavior Before deleting a resource, `agents resource remove` must check whether the resource is linked to any project. If it is, the command must fail with a clear error message such as: ``` Error: Cannot remove resource 'local/my-repo': it is linked to 1 project(s). Use 'agents project unlink-resource <project> local/my-repo' first. ``` The check should query the `ProjectResourceLinkRepository` (or equivalent) for any links where `resource_id` matches the resource being deleted. ## Acceptance Criteria 1. `agents resource remove <resource>` fails with exit code 1 and a descriptive error message when the resource is linked to one or more projects. 2. The error message names the number of projects the resource is linked to and instructs the user to use `agents project unlink-resource` first. 3. `agents resource remove <resource>` succeeds when the resource is not linked to any project (existing behavior preserved). 4. A BDD scenario is added to `features/resource_cli.feature` (or a new feature file) covering the "remove fails when linked to project" case. 5. All existing tests continue to pass. ## Supporting Information - Spec reference: `docs/specification.md`, line 10954 (section "agents resource remove") - Implementation: `src/cleveragents/cli/commands/resource.py`, function `resource_remove` (around line 1346) - Related: `src/cleveragents/cli/commands/project.py` — `_get_resource_link_repo()` helper already exists and can be reused ## Subtasks - [ ] Add project-link check in `resource_remove` before the DAG edge check - [ ] Return a clear error message listing the number of linked projects - [ ] Tests (Behave): Add scenario "Remove resource linked to project fails" in `features/resource_cli.feature` - [ ] Tests (Behave): Add scenario "Remove resource not linked to project succeeds" (regression guard) - [ ] Run `nox` (all default sessions), fix any errors - [ ] Verify coverage >=97% via `nox -s coverage_report` ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - 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. --- **Automated by CleverAgents Bot** Agent: new-issue-creator
HAL9000 added this to the v3.2.0 milestone 2026-04-14 12:56:12 +00:00
Author
Owner

Triage: Verified [AUTO-OWNR-1]

Valid bug: agents resource remove does not check project links before deletion, potentially leaving orphaned project references. This is a data integrity issue.

Assigning to v3.2.0 as resource management is a core M3 feature. Priority Medium — data integrity issue with potential for orphaned references.

MoSCoW: Should Have — referential integrity checks are important for data consistency.


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

✅ **Triage: Verified** [AUTO-OWNR-1] Valid bug: `agents resource remove` does not check project links before deletion, potentially leaving orphaned project references. This is a data integrity issue. Assigning to **v3.2.0** as resource management is a core M3 feature. Priority **Medium** — data integrity issue with potential for orphaned references. MoSCoW: **Should Have** — referential integrity checks are important for data consistency. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
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.

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