Skip to content

fix: release watched_repos on offboard so re-hire isn't blocked#32

Merged
michaelzwang13 merged 1 commit into
mainfrom
fix/offboard-cleans-watched-repos
May 25, 2026
Merged

fix: release watched_repos on offboard so re-hire isn't blocked#32
michaelzwang13 merged 1 commit into
mainfrom
fix/offboard-cleans-watched-repos

Conversation

@michaelzwang13
Copy link
Copy Markdown
Owner

@michaelzwang13 michaelzwang13 commented May 24, 2026

Closes #31.

What was broken

Offboarding (`DELETE /agents/{id}`) calls `Orchestrator.stop_agent`, which only sets `status='stopped'` and clears the container + token — the DB row stays, so the `on delete cascade` on `watched_repos` never fires.

Combined with #28's cross-agent uniqueness (`unique(user_id, owner, repo)`), a fired employee's stale `watched_repos` row permanently occupied the `(user, owner, repo)` slot. Re-hiring under the same user and re-subscribing to the same repo returned a 409 against a row tied to a stopped agent.

Why #28 is still correct

Two different users can still watch the same repo — the constraint is per `user_id`, not global. So a senior engineer and another senior engineer (different accounts) can both auto-review a junior's PR. Only intra-user duplicates are blocked. The fix is purely about the stale-row-after-stop case.

Fix

`Orchestrator.stop_agent` now calls `WatchedRepoModel.delete_by_agent(agent_id)` before the AgentModel.update that flips the status to `stopped`. Three observations:

  • `agent_memory`, `agent_action_log`, `reviewed_prs` are deliberately untouched. They're the audit trail of what the agent actually did. Offboard means "stop working," not "erase ever existed." Recommended option from the issue.
  • No new migration. The cleanup is at the model layer; existing schema unchanged.
  • Fire-and-forget. `delete_by_agent` returns nothing — we don't care about the row count.

Test

One new test in `TestStopAgent` (`test_stop_agent_releases_watched_repos`) patches `WatchedRepoModel.delete_by_agent` and asserts it was called with the right agent_id. Full suite: 142 → 143 passing.

Test plan

  • `pytest` passes (143/143)
  • Manual: hire CRE A, subscribe to repo X, offboard A, hire CRE B, subscribe B to repo X — should now 201 instead of 409

🤖 Generated with Claude Code

Closes #31.

Offboarding (DELETE /agents/{id}) sets status='stopped' but doesn't
delete the DB row, so the cascade on watched_repos never fired — and
the cross-agent uniqueness from #28 then blocked a new agent under the
same user from re-subscribing to the same repo. Stale watcher row tied
to a stopped agent permanently occupied the (user, owner, repo) slot.

Targeted cleanup in Orchestrator.stop_agent via a new
WatchedRepoModel.delete_by_agent. agent_memory, agent_action_log, and
reviewed_prs are deliberately left alone — they're the audit trail of
what the agent actually did, and offboard means "stop working," not
"erase ever existed."

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Owner Author

@michaelzwang13 michaelzwang13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ✅

Review Summary:

This is a clean, well-documented fix for the offboarding issue (#31).

What I like:

  • Correct root cause fix: Releasing watched_repos before the agent status update allows the cascade to work properly
  • Audit trail preserved: Keeping agent_memory, agent_action_log, and reviewed_prs is the right call for compliance
  • Good test coverage: The new test verifies delete_by_agent is called with the correct agent_id
  • Clear documentation: Comments reference #31 and #28, explaining the "why"
  • Minimal/surgical change: Only 51 lines added, no schema migration needed

The fix correctly balances cleanup (releasing repo subscriptions) with audit preservation (keeping action logs). Code looks ready to merge — would APPROVE if GitHub allowed self-approvals.

@michaelzwang13 michaelzwang13 merged commit 7331989 into main May 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Offboarding leaves watched_repos rows behind, blocking re-hire

1 participant