Context: When the OpenAI Privacy Filter (opf) binary is missing, hangs, or times out, every subsequent *WithPrivacyFilter entry point still tries to invoke it. With the default 30s timeout, one broken install turns a single condensation (or entire doctor bundle) into N × 30s waits instead of a single warning + graceful fallback.
Proposed fix: Process-scoped sticky atomic flag in redact/opf.go. First detectOPF failure trips it via handleOPFFailure; subsequent detectOPF calls short-circuit before shelling out. Resets on ConfigurePrivacyFilter and ResetOPFConfigForTest.
Why deferred from #1214: The original PR scope was "add OPF as opt-in layer." This is failure-mode hardening that should land separately.
Acceptance:
- First
detectOPF error in a process logs the warning + prints to TTY (existing behavior)
- Subsequent calls return
nil without invoking the runtime
- Reconfigure resets the breaker
- Unit test pins the contract
Context: When the OpenAI Privacy Filter (
opf) binary is missing, hangs, or times out, every subsequent*WithPrivacyFilterentry point still tries to invoke it. With the default 30s timeout, one broken install turns a single condensation (orentire doctor bundle) into N × 30s waits instead of a single warning + graceful fallback.Proposed fix: Process-scoped sticky atomic flag in
redact/opf.go. FirstdetectOPFfailure trips it viahandleOPFFailure; subsequentdetectOPFcalls short-circuit before shelling out. Resets onConfigurePrivacyFilterandResetOPFConfigForTest.Why deferred from #1214: The original PR scope was "add OPF as opt-in layer." This is failure-mode hardening that should land separately.
Acceptance:
detectOPFerror in a process logs the warning + prints to TTY (existing behavior)nilwithout invoking the runtime