What happens
Offboarding an agent (`DELETE /agents/{id}`) calls `Orchestrator.stop_agent`, which only sets `status='stopped'` and clears `container_id` / `agent_token`. The DB row stays, so the cascade-delete on `watched_repos` doesn't fire.
Net effect: a fired employee continues to occupy their repo subscriptions. If the user re-hires (or hires any other agent) and tries to subscribe to the same repo, the cross-agent uniqueness constraint from #28 (`unique(user_id, owner, repo)`) returns 409 against a stale row tied to a now-stopped agent.
Repro
```bash
curl -X POST .../agents -d '{"role":"code-review-engineer"}' # hire A
curl -X POST .../agents/A/watched-repos -d '{"owner":"x","repo":"y"}' # subscribe → 201
curl -X DELETE .../agents/A # offboard → 204
curl -X POST .../agents -d '{"role":"code-review-engineer"}' # hire B
curl -X POST .../agents/B/watched-repos -d '{"owner":"x","repo":"y"}' # 409 ← bug
```
Confirmed in real testing (smoke for PR #29).
Note on scope (#28 is still correct)
The `unique(user_id, owner, repo)` from #28 is the right constraint — two different users can still watch the same repo (e.g., two senior engineers reviewing a junior's PR get a copy each). The bug is purely about stopped agents under the same user occupying the slot.
Fix options
- Targeted cleanup — `stop_agent` also deletes `WatchedRepoModel` rows for the agent. Surgical; preserves the rest of the audit (`agent_action_log`, `reviewed_prs`).
- Hard-delete the agent row — change offboard to actually `DELETE FROM agents`, cascading to `watched_repos` / `agent_memory` / `agent_action_log` / `reviewed_prs`. Cleaner, but loses the audit trail entirely.
Recommended: option 1. Audit history of a fired employee is valuable for "what did this agent actually do." The offboard intent is "stop working," not "erase ever existed."
Done when
- After `DELETE /agents/{id}`, the agent's `watched_repos` rows are gone.
- A new agent under the same user can subscribe to the previously-watched (owner, repo) without 409.
- `agent_memory` / `agent_action_log` / `reviewed_prs` are preserved (untouched by offboard).
- One test in `test_orchestrator.py` covers the cleanup.
~30 lines of code. One-liner in spirit, but needs a test.
What happens
Offboarding an agent (`DELETE /agents/{id}`) calls `Orchestrator.stop_agent`, which only sets `status='stopped'` and clears `container_id` / `agent_token`. The DB row stays, so the cascade-delete on `watched_repos` doesn't fire.
Net effect: a fired employee continues to occupy their repo subscriptions. If the user re-hires (or hires any other agent) and tries to subscribe to the same repo, the cross-agent uniqueness constraint from #28 (`unique(user_id, owner, repo)`) returns 409 against a stale row tied to a now-stopped agent.
Repro
```bash
curl -X POST .../agents -d '{"role":"code-review-engineer"}' # hire A
curl -X POST .../agents/A/watched-repos -d '{"owner":"x","repo":"y"}' # subscribe → 201
curl -X DELETE .../agents/A # offboard → 204
curl -X POST .../agents -d '{"role":"code-review-engineer"}' # hire B
curl -X POST .../agents/B/watched-repos -d '{"owner":"x","repo":"y"}' # 409 ← bug
```
Confirmed in real testing (smoke for PR #29).
Note on scope (#28 is still correct)
The `unique(user_id, owner, repo)` from #28 is the right constraint — two different users can still watch the same repo (e.g., two senior engineers reviewing a junior's PR get a copy each). The bug is purely about stopped agents under the same user occupying the slot.
Fix options
Recommended: option 1. Audit history of a fired employee is valuable for "what did this agent actually do." The offboard intent is "stop working," not "erase ever existed."
Done when
~30 lines of code. One-liner in spirit, but needs a test.