ADR 0005: Keep resource lifecycle families explicit
- Status: Accepted
- Date: 2026-02-25
Context
The plugin enforces cleanup obligations for runtime resource families:
- timers and animation callbacks,
- DOM and Node event listeners,
- observers,
- abort controllers and abort signals,
- workers and child processes,
- streams,
- and explicit disposable resources.
These APIs share the same broad failure mode: code allocates work that can outlive the current scope, then loses the handle needed to stop it. They do not share the same cleanup primitive. A timer must be cleared, a listener must be removed with the same target/type/callback tuple, an observer must disconnect, a process must be killed or awaited, and a stream may need destroy/end/close semantics.
Treating every cleanup rule as one generic pattern would create noisy diagnostics and weak migration advice.
Decision
Keep cleanup rule families explicit in names, docs, tests, and presets.
- Timer rules focus on retaining handles from APIs such as
setTimeout,setInterval,requestAnimationFrame, and related globals. - Listener rules must prove that the callback and target can be paired with a later removal.
- Observer rules must reason about observer instance lifetime and
disconnect(). - Abort-controller rules must reason about signal propagation and abort ownership.
- Worker, stream, child-process, and disposable rules must each document their resource-specific cleanup semantics.
Shared infrastructure can normalize rule metadata, docs URLs, and preset wiring, but matcher logic should stay close to the resource family it understands.
Rationale
- Clear cleanup advice: diagnostics should name the exact handle or API the developer must preserve.
- Lower false-positive risk: resource-specific matchers avoid pretending that every lifecycle API can be analyzed the same way.
- Better rule authoring discipline: tests can cover the actual cleanup primitive instead of broad, generic leak language.
- Safer preset design: stable presets can include syntax-only, low-noise checks while semantic ownership rules mature separately.
Consequences
- Documentation and changelogs should identify the resource family a rule belongs to.
- New rules should declare their cleanup primitive and detection boundary up front.
- Autofixes should be rare for cleanup rules because safe cleanup location is usually semantic; suggestions are acceptable when they preserve intent.
- Preset promotion should be based on false-positive behavior per family, not on nominal API coverage.
Revisit Triggers
Re-evaluate if:
- the project introduces a shared ownership model that can safely cover multiple resource families,
- or users report that the current family split no longer reflects how cleanup work is reviewed.