Per-system correlation_enabled=false is ignored: the call still correlates, with empty tags, down the thin/recency path #75

Closed
opened 2026-08-25 21:30:50 -04:00 by logan · 1 comment
Owner

Found by the standing correlation pass on the 2026-08-25 evening unattended run.

The defect

app/routers/upload.py resolves AI feature flags through a local _flag() helper (:276-280) that correctly applies per-system ai_flags overrides on top of the global config/ai_features document. Step 1 (STT, :286) and Step 2's entry (:298) both use it.

Line 313 does not. It tests the raw global flags["correlation_enabled"] instead of _flag("correlation_enabled").

Failure scenario

Global correlation_enabled = true, one system opted out via its own ai_flags.correlation_enabled = false:

  1. The opted-out system's call reaches Step 2.
  2. Scene extraction is skipped — scenes stays empty.
  3. The if not scenes fallback (:347-362) runs anyway and correlates the call with empty tags.
  4. Empty tags means no content signal, so it takes the thin/recency path and links into whatever incident is most recent on that system.

So the per-system opt-out does not opt the system out of correlation. It opts it out of good correlation and leaves it doing the worst kind — blind recency attachment.

Impact

This is the control you would reach for to keep a noisy or low-value system out of a paid AI evaluation window, or to bound spend for a comped friends-and-family node (#50). It does not hold. Anyone who has set it believes they are protected and is not.

Both live systems currently have correlation_enabled = true, so this did not affect the 2026-08-25 window.

Fix

Change :313 to _flag("correlation_enabled"). Add a test asserting that a system-level false under a global true produces neither extraction nor a correlation attempt.

Note on shipping this

routers/upload.py is one of the four files board minutes #62 decision 9 froze for autonomous push to main until the deploy rollback (#65) lands.

Refs #50, #45, #65, #62.

Found by the standing correlation pass on the 2026-08-25 evening unattended run. ## The defect `app/routers/upload.py` resolves AI feature flags through a local `_flag()` helper (`:276-280`) that correctly applies per-system `ai_flags` overrides on top of the global `config/ai_features` document. Step 1 (STT, `:286`) and Step 2's entry (`:298`) both use it. **Line 313 does not.** It tests the raw global `flags["correlation_enabled"]` instead of `_flag("correlation_enabled")`. ## Failure scenario Global `correlation_enabled = true`, one system opted out via its own `ai_flags.correlation_enabled = false`: 1. The opted-out system's call reaches Step 2. 2. Scene extraction is skipped — `scenes` stays empty. 3. The `if not scenes` fallback (`:347-362`) runs anyway and correlates the call with **empty tags**. 4. Empty tags means no content signal, so it takes the thin/recency path and links into whatever incident is most recent on that system. So the per-system opt-out does not opt the system out of correlation. It opts it out of *good* correlation and leaves it doing the worst kind — blind recency attachment. ## Impact This is the control you would reach for to keep a noisy or low-value system out of a paid AI evaluation window, or to bound spend for a comped friends-and-family node (#50). It does not hold. Anyone who has set it believes they are protected and is not. Both live systems currently have `correlation_enabled = true`, so this did **not** affect the 2026-08-25 window. ## Fix Change `:313` to `_flag("correlation_enabled")`. Add a test asserting that a system-level `false` under a global `true` produces neither extraction nor a correlation attempt. ## Note on shipping this `routers/upload.py` is one of the four files board minutes #62 decision 9 froze for autonomous push to `main` until the deploy rollback (#65) lands. Refs #50, #45, #65, #62.
Author
Owner

Fixed and deployed. d18e4f0, live on prod /health at 2026-08-27 06:55 UTC.

upload.py:313 now resolves through the per-system helper instead of the raw global flag, so a system with ai_flags.correlation_enabled = false under a global true gets no scene extraction and no correlation attempt — including the empty-scenes fallback, which was the actual harm. The opt-out no longer degrades the system to blind recency attachment.

Root cause was structural, so the fix is too: the resolver moved out of upload.py into feature_flags.resolve_flags(). It had been a local helper, which is exactly why one of its three call sites could drift out of sync without anything noticing. transcription.py and calls.py now use the same function.

Tests added as this issue asked (tests/test_ai_flag_gating.py):

  • a 5-case precedence matrix over resolve_flags (system false beats global true; global false beats everything; absent key inherits);
  • test_per_system_opt_out_blocks_the_blind_recency_fallback_too, which asserts _correlate_with_consensus is never awaited — this is the specific regression guard, since skipping extraction alone was never the bug;
  • the positive case, so the test cannot pass by accident on a system that correlates nothing.

Suite: 264 passed, 0 failed. Reviewed by the correlation pass before push (initial verdict HOLD on an unrelated defect in the same diff, re-verified SHIP after the fix).

Closing.

**Fixed and deployed. `d18e4f0`, live on prod `/health` at 2026-08-27 06:55 UTC.** `upload.py:313` now resolves through the per-system helper instead of the raw global flag, so a system with `ai_flags.correlation_enabled = false` under a global `true` gets no scene extraction **and** no correlation attempt — including the empty-scenes fallback, which was the actual harm. The opt-out no longer degrades the system to blind recency attachment. Root cause was structural, so the fix is too: the resolver moved out of `upload.py` into `feature_flags.resolve_flags()`. It had been a local helper, which is exactly why one of its three call sites could drift out of sync without anything noticing. `transcription.py` and `calls.py` now use the same function. Tests added as this issue asked (`tests/test_ai_flag_gating.py`): - a 5-case precedence matrix over `resolve_flags` (system false beats global true; global false beats everything; absent key inherits); - `test_per_system_opt_out_blocks_the_blind_recency_fallback_too`, which asserts `_correlate_with_consensus` is never awaited — this is the specific regression guard, since skipping extraction alone was never the bug; - the positive case, so the test cannot pass by accident on a system that correlates nothing. Suite: 264 passed, 0 failed. Reviewed by the correlation pass before push (initial verdict HOLD on an unrelated defect in the same diff, re-verified SHIP after the fix). Closing.
logan closed this issue 2026-08-27 02:56:25 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logan/server-26#75