ekp/postmortem/20260728-public-filter-dispatch.md
Kinneyzhang fd1210e557 fix: close repository audit findings
Complete task002 through task016 across cache correctness, editor lifecycle, C boundaries, build and release governance, dictionary provenance, performance, interactive workflows, tests, documentation, and final cleanup.
2026-07-28 22:43:10 +08:00

2.3 KiB

Use the Public Substring Filter Dispatcher

Context

EKP correctly preserved a prior filter-buffer-substring-function, but invoked it through Emacs's private buffer-substring--filter helper. That made the integration depend on an implementation detail outside EKP's ownership and version baseline.

Decision

During EKP extraction, dynamically bind filter-buffer-substring-function to the recorded prior value and call public filter-buffer-substring. Inhibit EKP lifecycle cleanup while that temporary binding is active. For a DELETE operation, unwind the binding first and then reconcile integration ownership against the buffer's actual filter slot.

Failed First Repair

The first public-dispatch repair allowed after-change cleanup to run under the temporary prior-filter binding. The focused kill/DELETE regression failed because cleanup cleared EKP ownership state without restoring the real EKP-bound slot. That failure narrowed the problem to lifecycle ordering; no second speculative behavior patch was stacked on it.

Alternatives Rejected

Keep Calling the Private Helper

It works on the current Emacs build but violates the dependency boundary and makes the documented Emacs baseline depend on unowned internals.

Reimplement Prior-Filter Dispatch

Duplicating Emacs's filtering and deletion semantics would create a second protocol implementation and a larger compatibility surface.

Run Cleanup Before Unwinding

The dynamic prior-filter binding is not the buffer's durable ownership state, so lifecycle decisions made there are necessarily wrong-layer decisions.

Consequences

  • Prior local and inherited filter behavior still composes through the public dispatcher.
  • DELETE cleanup observes the real post-operation ownership slot.
  • Internal filter calls can no longer drift independently from Emacs's public dispatcher contract.
  • Errors from a prior filter still propagate; no fallback or swallowing path was added.

Verification

The first repair failed the public kill/DELETE lifecycle regression. The ordering repair passes all five composition/lifecycle cases. The final private-boundary scan contains no buffer-substring--filter use in runtime or tests.

Rollback

Restore direct private-helper dispatch. No persisted data needs migration, but doing so reintroduces the unowned dependency boundary.