Scene correlation is judged on the call-level (primary-scene) embedding and severity, not the scene it is correlating #80
Closed
opened 2026-08-26 09:31:11 -04:00 by logan
·
5 comments
No Branch/Tag Specified
Labels
Clear labels
area/ai-pipeline
area/auth
area/billing
area/correlation
area/discord
area/frontend
area/governance
area/growth
area/infra-deploy
area/legal
area/map
area/mqtt
area/node-ota
area/osint
area/recording-audio
area/sdr-radio
area/transcription
board
board:agenda
minutes:draft
minutes:final
role:ceo
role:cfo
role:cio
role:ciso
role:cmo
role:coo
role:cto
Scene/entity extraction, summarizer, AI providers, embeddings
AuthN/Z, roles, tenancy/org scoping, API keys, credentials
Plans, entitlements, AI spend accounting and caps
Incident correlation, linking, lifecycle, severity, corr_debug
Discord bot, radio bots, voice streams, bot tokens, webhooks
Web UI: Next.js app and the edge-node local dashboard
Board process, minutes, unattended runner, agent tooling
Go-to-market, outreach, cold email, discovery conversations
CI/CD, VM, registry, Firestore rules/indexes deploy, Terraform/Caddy
ToS, retention, licences/DAAs, CAN-SPAM, E&O, name suppression
Live map: pins, paths, tiles, legend, geocoding
Node-C2 MQTT, checkins, commands, node sweeper, dynsec
Node install, enrollment, OTA updater, image skew
External feeds: cameras, 511, ADS-B, AIS, outages, and their licences
Call capture, boundaries, PulseAudio, ring buffer, trimming, attribution
OP25 decode, SDR hardware/tuning, conventional, second SDR, mesh radio
STT, transcript correction, place verification, name accuracy
Board process: minutes and board-filed items
Needs board scoping at the next sitting; CEO removes the label once scoped
One exec pre-read, closed by CEO
CEO ruling; open until enacted
Filed by the CEO
Filed by the CFO
Filed by the CIO
Filed by the CISO
Filed by the CMO
Filed by the COO
Filed by the CTO
kind
behavior-bug
Wrong product behavior; the instrument reads it correctly
kind
measurement-bug
Corrupts the recording/instrument (debug data, evals, health checks), not behavior
priority
p0
Drop everything: prod broken, live exposure, or owner-ruled P0
priority
p1
Next up: blocks a gate, a customer, or core incident quality
priority
p2
Normal: real defect or planned work, schedule in turn
priority
p3
Low: minor, cosmetic, or someday
status
blocked
Waiting on an external party, spend, or another issue
status
in-progress
Branch or PR open against it
status
needs-decision
Waiting on an owner or board ruling before work
status
needs-info
Root cause or repro unknown; needs a reading first
type
bug
Something built is wrong: code, data, or a measurement
type
chore
Maintenance, refactor, tests, pinning, cleanup: no user-visible change
type
decision
A ruling to make or record: board minutes, owner calls, legal reviews
type
docs
Docs, runbooks, CLAUDE.md, skills, SOPs
type
feature
New capability or an extension of an existing one
type
security
Security, privacy, credential or tenant-isolation exposure
type
tracking
Tracker, checklist, initiative or punch-list spanning several changes
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: logan/server-26#80
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found during the standing correlation static pass, 2026-08-26. Not a duplicate of the DEFERRED.md multi-scene entry: that entry is about link fan-out, this is about the wrong content reaching the one guard that bounds over-merging.
What happens
intelligence.pywrites only the primary scene embedding to the call document._build_contextinincident_correlator.pythen readscall_embedding/call_severityback off that document, and_correlate_with_consensusnever passes a per-scene embedding or severity.So on any multi-scene call, every scene after the first is judged on scene 1 content by:
Why it compounds
The incident that scene 2 links to (or creates) then stores scene 1 embedding. That poisons the divergence check for every later call tested against that incident. The error does not stay local to one call.
Direction
Over-merging. The veto that exists to break unit-overlap feedback is precisely the thing being fed the wrong vector.
Fix shape
Pass
scene["embedding"]andscene["severity"]throughpreview_correlationintoctx, falling back to the call document when a scene does not carry them. No threshold change, so it does not trade against the over-splitting currently measured on the main path (see #5).Not verified
No live window this run (morning slot, AI off for cost). Static read only, and neither
upload.pynor the fit function has test coverage.Refs #5, #35, #74.
Confirmed with a concrete mechanism by the standing correlation pass, unattended run 2026-08-27.
intelligence.py:356writes only the primary scene'sseverityto the call doc, and:368only the primary scene'sembedding. But_build_context(incident_correlator.py:784) re-readscall_doc["severity"]for every scene's_is_thin_callcheck.Consequence: a "10-4" second scene on a call whose first scene was
majoris never judged thin. It falls through to the fit path, returnsno_signalon a dispatch channel, and opens its own incident.Direction: over-splitting — and it is a new mechanism created by the
_is_thin_calltightening, not the multi-scene case already described inDEFERRED.md.Same line is the concrete evidence for this issue's premise: per-scene embeddings are computed at
intelligence.py:329and then discarded, so the content-divergence veto judges scene N against scene 1's vector.Not fixed this run. Fixing it means writing per-scene severity and embedding through to whatever
_build_contextreads, which is a correlation-behaviour change that wants its own evaluation window rather than riding along with unrelated work.Extends this issue — same root cause, same fix site, two more fields. Static pass, unattended run 2026-08-28, at
d18e4f0.This issue names the embedding and severity as the fields that bleed from the primary scene. There are two more, and one of them is worse than either, because it does not merely mis-score a guard — it manufactures a positive fit signal out of nothing.
location_coordsbleeds too._build_contexttakeslocation,tagsandunitsper scene, but falls back to the call document for the rest:coords = location_coords or call_doc.get("location_coords")(incident_correlator.py, in_build_context)call_severity = call_doc.get("severity")(same function)and
intelligence.pywrites onlyprimary["location_coords"]andprimary["severity"]onto the call doc. So scene 2 — which usually has no geocode of its own — is fit-tested against scene 1's pin.Two distinct consequences, neither of which the embedding/severity story covers:
location_proximityon coordinates belonging to a different event. That is not a weakened veto; it is a fabricated positive.coordstruthy, scene 2 is never thin, so it takes the slow path and skips the thin-call tiering entirely.Both push the same direction this issue already names — over-merge — and both amplify the fan-out.
Fix shape is unchanged, just wider: pass
scene["location_coords"]andscene["severity"]throughpreview_correlationintoctxalongside the embedding, falling back to the call document only when the scene genuinely does not carry them. One change, four fields.Cost note, same file.
intelligence.pycomputes and pays for a per-scene embedding, but only the primary's is ever written to the call doc and therefore only the primary's ever reaches the correlator. Every secondary scene's embedding is bought and discarded. That is measurable spend against Gate B5 (#45) with no consumer.Not verified: no live window this run (02:37 slot, AI off for cost). Static read only. The multi-scene path still has zero test coverage, so the coords bleed is read from source and unexercised — worth a test alongside the fix rather than after it.
Refs #5, #35, #45, #74.
Confirmed and sharpened at
29c2fb1, static correlation pass, unattended run 2026-08-31. This issue is correct, and it is a stronger over-merging force than server-26#87 - which was fixed tonight on the geocode channel only. Same leak, different channel.The per-scene embedding is computed and then thrown away:
intelligence.py:329embeds each scene.intelligence.py:369writes onlyprimary["embedding"]to the call doc._build_contextreadscall_doc.get("embedding")(incident_correlator.py:780), because_correlate_with_consensushas no embedding parameter at all (upload.py:210-224).So a non-primary scene is correlated on the primary scene's content. That propagates into three places:
incident_correlator.py:1212),:1174),:1636,:1649), which compares scene 1's embedding against an incident built from scene 1.That third consequence is the one that matters. The veto is structurally incapable of firing for a non-primary scene: it is asked whether a thing diverges from itself. So the over-merge veto that server-26#86 proposes to tune is, for every non-primary scene, not merely mis-thresholded but inoperative.
Also: the discarded per-scene embeddings are paid for. Every extra scene on a call buys an embedding call whose result is written nowhere.
The fix is not a threshold change. It is threading the scene's own embedding through
_correlate_with_consensusinto_build_contextso each scene is judged on its own content. That is a signature change acrossupload.pyandincident_correlator.py, which is why it was not taken in the same run as #87.Sequencing note. #86 must not be tuned before this lands. Tuning a veto that cannot fire for the affected population would fit the threshold to the wrong data.
Now higher-priority than when filed, and it has a sibling. Unattended run 2026-09-01.
bdb57ae(#87, live) removed the third channel of the same leak — the call doc'slocation_coordsfallback in_build_context. The primary-scene leak had three channels; coords was the one that got fixed. This issue (embedding,incident_correlator.py:780) and the newly filed #95 (severity,:784) are the two that remain, and they now carry the full weight of the primary scene's identity alone.Both have the same root:
intelligence.pyunionstags,unitsandvehiclesacross scenes but writesseverity(:356) andembedding(:368) fromprocessed[0]only.Fix #95 and this one in a single pass. They are one defect with two field names, and doing them separately repeats exactly the partial-fix pattern that
bdb57aeleft behind. The fix shape is the onebdb57aealready established for coords: make the value per-scene in the extraction output and read the scene's own value with no call-doc fallback.No test covers
_build_context's embedding or severity sourcing — the fix needs a multi-scene fixture where scene 1 ismajorand scene 2 is content-free.Fixed in
a9d1d24(branchfix/scene-context-leak-80-95, not yet merged/deployed)._build_contextno longer readsembedding/severityoff the call doc — each scene threads its own value throughpreview_correlation/correlate_call, exactly like the #87 coords fix.recorrelation_sweeppasses the call doc value explicitly (whole-call re-link, link-only). +2 regression tests intest_incident_identity.py; full c2-core suite green (295 passed).Remaining leg of this defect class split to #102 (
llm_correlator._call_blockstill reads the whole-call transcript per scene). Review-flagged side effects: #103 (divergence veto on None embedding), #104 (reprocess stale severity).