UAT: agents resource remove checks ResourceEdgeModel (resource_edges table) for edges but DAG links are stored in ResourceLinkModel (resource_links table) — dangling links after removal #2837

Open
opened 2026-04-04 20:46:20 +00:00 by freemo · 1 comment
Owner

Background

The resource_remove CLI command in src/cleveragents/cli/commands/resource.py (around line 1290) checks for existing DAG edges using ResourceEdgeModel (which queries the resource_edges table) before allowing deletion. However, the link_child / unlink_child operations in _resource_registry_dag.py store DAG relationships in ResourceLinkModel (which queries the resource_links table).

This means:

  1. User calls agents resource link-child parent child → link stored in resource_links table via ResourceLinkModel
  2. User calls agents resource remove child → CLI checks resource_edges table via ResourceEdgeModel → finds 0 edges → allows deletion
  3. The resource_links table now has a dangling reference to the deleted resource's ID

Expected behavior: agents resource remove should check BOTH ResourceEdgeModel (resource_edges) AND ResourceLinkModel (resource_links) for existing DAG relationships before allowing deletion. If any links exist in either table, the removal should be rejected with a clear error message.

Actual behavior: agents resource remove only checks ResourceEdgeModel (resource_edges table). Links created via agents resource link-child (stored in resource_links table via ResourceLinkModel) are NOT checked. This allows deletion of resources that still have active DAG parent/child relationships, leaving dangling foreign key references in the resource_links table.

Severity: High — data integrity violation; DAG consistency is broken silently.

Steps to Reproduce

  1. agents resource add git-checkout local/parent-repo --path /tmp/parent
  2. agents resource add fs-directory local/child-dir --path /tmp/child
  3. agents resource link-child local/parent-repo local/child-dir → stored in resource_links
  4. agents resource remove local/child-dir → succeeds (should fail!)
  5. Check resource_links table → dangling row with child_id pointing to deleted resource

Code Locations

  • src/cleveragents/cli/commands/resource.py ~line 1290: checks ResourceEdgeModel only
  • src/cleveragents/application/services/_resource_registry_dag.py lines 104, 138, 173, 210, 266: uses ResourceLinkModel for all DAG operations
  • src/cleveragents/infrastructure/database/models.py: defines both ResourceEdgeModel (table: resource_edges) and ResourceLinkModel (table: resource_links) as separate models

Metadata

  • Branch: fix/resource-remove-check-resource-links
  • Commit Message: fix(cli): check ResourceLinkModel in resource remove to prevent dangling DAG links
  • Milestone: v3.7.0
  • Parent Epic: #398

Subtasks

  • Audit resource_remove in src/cleveragents/cli/commands/resource.py (~line 1290) to understand the current edge-check logic using ResourceEdgeModel
  • Add a pre-deletion guard that queries ResourceLinkModel for any rows where parent_id OR child_id matches the resource being removed
  • Ensure the combined check (both ResourceEdgeModel and ResourceLinkModel) raises a clear, user-facing error message listing the conflicting links if any are found
  • Write Behave unit tests (in features/) covering: removal blocked when resource_links row exists as parent, removal blocked when resource_links row exists as child, removal succeeds when neither table has references
  • Write Robot Framework integration tests (in robot/) reproducing the exact steps-to-reproduce scenario end-to-end
  • Run nox -e typecheck and confirm no Pyright errors introduced
  • Run nox -e lint and confirm no linting violations
  • Run nox -e unit_tests and confirm all Behave scenarios pass
  • Run nox -e integration_tests and confirm Robot Framework tests pass
  • Run nox -e coverage_report and confirm coverage remains ≥ 97%

Definition of Done

  • All subtasks above are checked off
  • agents resource remove rejects deletion of any resource that has active entries in either resource_edges OR resource_links tables, with a descriptive error message
  • No dangling rows are left in resource_links after any resource remove operation
  • Commit created with exact message: fix(cli): check ResourceLinkModel in resource remove to prevent dangling DAG links with footer ISSUES CLOSED: #<this issue number>
  • Commit pushed to branch fix/resource-remove-check-resource-links
  • Pull Request opened, linked to this issue, and merged
  • All nox stages pass
  • Coverage >= 97%

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

## Background The `resource_remove` CLI command in `src/cleveragents/cli/commands/resource.py` (around line 1290) checks for existing DAG edges using `ResourceEdgeModel` (which queries the `resource_edges` table) before allowing deletion. However, the `link_child` / `unlink_child` operations in `_resource_registry_dag.py` store DAG relationships in `ResourceLinkModel` (which queries the `resource_links` table). This means: 1. User calls `agents resource link-child parent child` → link stored in `resource_links` table via `ResourceLinkModel` 2. User calls `agents resource remove child` → CLI checks `resource_edges` table via `ResourceEdgeModel` → finds 0 edges → allows deletion 3. The `resource_links` table now has a dangling reference to the deleted resource's ID **Expected behavior**: `agents resource remove` should check BOTH `ResourceEdgeModel` (resource_edges) AND `ResourceLinkModel` (resource_links) for existing DAG relationships before allowing deletion. If any links exist in either table, the removal should be rejected with a clear error message. **Actual behavior**: `agents resource remove` only checks `ResourceEdgeModel` (resource_edges table). Links created via `agents resource link-child` (stored in `resource_links` table via `ResourceLinkModel`) are NOT checked. This allows deletion of resources that still have active DAG parent/child relationships, leaving dangling foreign key references in the `resource_links` table. **Severity**: High — data integrity violation; DAG consistency is broken silently. ## Steps to Reproduce 1. `agents resource add git-checkout local/parent-repo --path /tmp/parent` 2. `agents resource add fs-directory local/child-dir --path /tmp/child` 3. `agents resource link-child local/parent-repo local/child-dir` → stored in `resource_links` 4. `agents resource remove local/child-dir` → succeeds (should fail!) 5. Check `resource_links` table → dangling row with `child_id` pointing to deleted resource ## Code Locations - `src/cleveragents/cli/commands/resource.py` ~line 1290: checks `ResourceEdgeModel` only - `src/cleveragents/application/services/_resource_registry_dag.py` lines 104, 138, 173, 210, 266: uses `ResourceLinkModel` for all DAG operations - `src/cleveragents/infrastructure/database/models.py`: defines both `ResourceEdgeModel` (table: `resource_edges`) and `ResourceLinkModel` (table: `resource_links`) as separate models ## Metadata - **Branch**: `fix/resource-remove-check-resource-links` - **Commit Message**: `fix(cli): check ResourceLinkModel in resource remove to prevent dangling DAG links` - **Milestone**: v3.7.0 - **Parent Epic**: #398 ## Subtasks - [ ] Audit `resource_remove` in `src/cleveragents/cli/commands/resource.py` (~line 1290) to understand the current edge-check logic using `ResourceEdgeModel` - [ ] Add a pre-deletion guard that queries `ResourceLinkModel` for any rows where `parent_id` OR `child_id` matches the resource being removed - [ ] Ensure the combined check (both `ResourceEdgeModel` and `ResourceLinkModel`) raises a clear, user-facing error message listing the conflicting links if any are found - [ ] Write Behave unit tests (in `features/`) covering: removal blocked when `resource_links` row exists as parent, removal blocked when `resource_links` row exists as child, removal succeeds when neither table has references - [ ] Write Robot Framework integration tests (in `robot/`) reproducing the exact steps-to-reproduce scenario end-to-end - [ ] Run `nox -e typecheck` and confirm no Pyright errors introduced - [ ] Run `nox -e lint` and confirm no linting violations - [ ] Run `nox -e unit_tests` and confirm all Behave scenarios pass - [ ] Run `nox -e integration_tests` and confirm Robot Framework tests pass - [ ] Run `nox -e coverage_report` and confirm coverage remains ≥ 97% ## Definition of Done - [ ] All subtasks above are checked off - [ ] `agents resource remove` rejects deletion of any resource that has active entries in either `resource_edges` OR `resource_links` tables, with a descriptive error message - [ ] No dangling rows are left in `resource_links` after any `resource remove` operation - [ ] Commit created with exact message: `fix(cli): check ResourceLinkModel in resource remove to prevent dangling DAG links` with footer `ISSUES CLOSED: #<this issue number>` - [ ] Commit pushed to branch `fix/resource-remove-check-resource-links` - [ ] Pull Request opened, linked to this issue, and merged - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
freemo added this to the v3.7.0 milestone 2026-04-04 20:46:25 +00:00
Author
Owner

Starting implementation on branch fix/resource-remove-check-resource-links.

Analysis:

  • resource_remove in src/cleveragents/cli/commands/resource.py (~line 1295) only checks ResourceEdgeModel (resource_edges table) before allowing deletion
  • link_child/unlink_child operations in _resource_registry_dag.py store DAG relationships in ResourceLinkModel (resource_links table)
  • Fix: add a second query against ResourceLinkModel and combine both counts before rejecting deletion

Plan:

  1. Add ResourceLinkModel import to resource_remove
  2. Query ResourceLinkModel for parent_id OR child_id matches
  3. Combine edge_count + link_count; reject if either > 0 with descriptive error
  4. Write Behave BDD tests for the new scenarios
  5. Write Robot Framework integration test reproducing the exact steps-to-reproduce
  6. Run all quality gates

Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

Starting implementation on branch `fix/resource-remove-check-resource-links`. **Analysis:** - `resource_remove` in `src/cleveragents/cli/commands/resource.py` (~line 1295) only checks `ResourceEdgeModel` (resource_edges table) before allowing deletion - `link_child`/`unlink_child` operations in `_resource_registry_dag.py` store DAG relationships in `ResourceLinkModel` (resource_links table) - Fix: add a second query against `ResourceLinkModel` and combine both counts before rejecting deletion **Plan:** 1. Add `ResourceLinkModel` import to `resource_remove` 2. Query `ResourceLinkModel` for parent_id OR child_id matches 3. Combine edge_count + link_count; reject if either > 0 with descriptive error 4. Write Behave BDD tests for the new scenarios 5. Write Robot Framework integration test reproducing the exact steps-to-reproduce 6. Run all quality gates --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
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#2837
No description provided.