Skip to content

fix(incidents): a close releases the members that never left - #484

Merged
passcod merged 1 commit into
mainfrom
fix/release-incident-members-on-close
Aug 4, 2026
Merged

fix(incidents): a close releases the members that never left#484
passcod merged 1 commit into
mainfrom
fix/release-incident-members-on-close

Conversation

@passcod

@passcod passcod commented Aug 4, 2026

Copy link
Copy Markdown
Member

🤖 Stacked on #483, which made stranded membership rows inert. This stops making them, and retires the ones already there.

Closing an incident only ever retired the incidents row. The issue whose recovery triggered the close is stamped by the leave arm, but sub-failure contributors are held attached for context and nothing released them — their incident_issues rows survived the incident, claiming a membership that had ended.

release_remaining_members stamps whoever is left at each of the three closes — the leave arm, the linger sweep, and the operator resolve — with the timestamp that close was recorded at, so the membership ends exactly when the incident did. The sweep backdates to closing_at for the same reason the close does: the linger is damping machinery, not part of the incident's span. The operator path resolves each member individually and mostly drives them out through the leave arm, but a member already carrying resolved_at is skipped to preserve its audit trail and never leaves, so it needs the release too.

A data migration retires the rows already stranded, setting left_at to the close they outlived. Membership of a still-open incident is live and is left alone. Its down.sql is deliberately a no-op — nothing distinguishes a backfilled row from one the close paths stamped afterwards, so a revert would clear legitimate leaves and re-strand the memberships.

Incident detail reads every link and keeps the most recent per issue rather than filtering on left_at, so closed incidents still list who was involved.

Coverage

Three tests, one per side: the close releases a contributor that never left; a row stranded the way the old paths left it still lets a later failure open an incident; the backfill retires stranded rows and spares live ones.

The read fix made stranded rows inert; this stops making them. Closing an
incident only ever retired the incidents row: the issue whose recovery
triggered the close is stamped by the leave arm, but sub-failure
contributors are held attached for context and nothing released them, so
their membership rows survived the incident claiming a membership that had
ended.

release_remaining_members stamps whoever is left at each of the three
closes — the leave arm, the linger sweep, and the operator resolve — with
the timestamp that close was recorded at, so the membership ends exactly
when the incident did. The sweep backdates to closing_at for the same
reason the close does: the linger is damping machinery, not part of the
incident's span. The operator path resolves each member individually and
mostly drives them out through the leave arm, but a member already
carrying resolved_at is skipped to preserve its audit trail and never
leaves, so it needs the release too.

A data migration retires the rows already stranded, setting left_at to the
close they outlived. Membership of a still-open incident is live and is
left alone.

Incident detail reads every link and keeps the most recent per issue
rather than filtering on left_at, so closed incidents still list who was
involved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Base automatically changed from fix/stranded-incident-membership to main August 4, 2026 22:14
@passcod
passcod enabled auto-merge August 4, 2026 22:19
@passcod
passcod added this pull request to the merge queue Aug 4, 2026
Merged via the queue into main with commit 019a7e3 Aug 4, 2026
7 checks passed
@passcod
passcod deleted the fix/release-incident-members-on-close branch August 4, 2026 22:35
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.

1 participant