Cleanup webhooks — issues.closed and pull_request.merged #4

Closed
opened 2026-04-16 22:44:09 +00:00 by claude-desktop · 0 comments
Collaborator

User story

As ops, I want claude-hooks to drop persisted state for an issue or PR as soon as it closes/merges, so that worktrees and (later) session entries do not accumulate forever.

Acceptance criteria

New webhook routes (src/webhook.ts)

  • issues event with action === "closed" → call cleanupIssue(repo, issue_number) for each registered agent
  • pull_request event with action === "closed" and payload.pull_request.merged === true → derive the issue/branch and call cleanupIssue (or a parallel cleanupBranch) for the PR's source branch
  • Reopened issues (action === "reopened") are intentionally a no-op — no cleanup, no auto-redispatch
  • Bodies of these handlers stay short: delegate the actual filesystem/state work to a cleanup.ts module so the webhook layer stays declarative

cleanup.ts shim

  • Defines cleanupIssue(repo, issue_number, opts?) and cleanupBranch(repo, branch, opts?)
  • First implementation only logs the intent (so this PR can ship before the workdir module lands)
  • Once the workdir module merges, wire releaseWorktree({ keep: false }) for each agent
  • Once the sessions store ships, also call dropAllForIssue

Tests (src/webhook.test.ts)

  • Synthetic issues.closed payload triggers cleanupIssue once per agent
  • Synthetic pull_request.closed with merged: true triggers cleanupBranch
  • pull_request.closed with merged: false (i.e. closed without merging) also triggers cleanupBranch — discarded work shouldn't keep state either

Out of scope

  • The actual releaseWorktree call (lives in the workdir module's wiring story)
  • The actual session drop (lives in the sessions store story)
  • Sweeper for missed events (separate story)

References

  • Forgejo v15 event names: modules/webhook/type.go
  • Discussion: chat history, "Phase 1 — cleanup webhooks"

Dependencies

  • Blocked by: none (ships with stub cleanup.ts)
  • Blocks: #5
  • Branch off: main
  • Full graph: #10
## User story As **ops**, I want claude-hooks to drop persisted state for an issue or PR as soon as it closes/merges, so that worktrees and (later) session entries do not accumulate forever. ## Acceptance criteria ### New webhook routes (`src/webhook.ts`) - [ ] `issues` event with `action === "closed"` → call `cleanupIssue(repo, issue_number)` for each registered agent - [ ] `pull_request` event with `action === "closed"` and `payload.pull_request.merged === true` → derive the issue/branch and call `cleanupIssue` (or a parallel `cleanupBranch`) for the PR's source branch - [ ] Reopened issues (`action === "reopened"`) are intentionally a no-op — no cleanup, no auto-redispatch - [ ] Bodies of these handlers stay short: delegate the actual filesystem/state work to a `cleanup.ts` module so the webhook layer stays declarative ### `cleanup.ts` shim - [ ] Defines `cleanupIssue(repo, issue_number, opts?)` and `cleanupBranch(repo, branch, opts?)` - [ ] First implementation only logs the intent (so this PR can ship before the workdir module lands) - [ ] Once the workdir module merges, wire `releaseWorktree({ keep: false })` for each agent - [ ] Once the sessions store ships, also call `dropAllForIssue` ### Tests (`src/webhook.test.ts`) - [ ] Synthetic `issues.closed` payload triggers `cleanupIssue` once per agent - [ ] Synthetic `pull_request.closed` with `merged: true` triggers `cleanupBranch` - [ ] `pull_request.closed` with `merged: false` (i.e. closed without merging) also triggers `cleanupBranch` — discarded work shouldn't keep state either ## Out of scope - The actual `releaseWorktree` call (lives in the workdir module's wiring story) - The actual session drop (lives in the sessions store story) - Sweeper for missed events (separate story) ## References - Forgejo v15 event names: `modules/webhook/type.go` - Discussion: chat history, "Phase 1 — cleanup webhooks" ## Dependencies - **Blocked by:** none (ships with stub `cleanup.ts`) - **Blocks:** #5 - **Branch off:** `main` - **Full graph:** #10
Sign in to join this conversation.
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.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#4
No description provided.