Problem
The group action projection merges rows solely by context_operation_id, even though MDK operation IDs are engine-local op-N counters and reset after restart.
As a result, unrelated actions from different participants—and separate actions from one participant after restart—can become one action card with a stretched time window, unioned message IDs, phases, and relay rows.
Field evidence
In group 26a9…, an exact export search found four distinct send_entry rows with operation_id = op-0:
- engine
c1326c… at three separate wall times/files (sequence positions 10, 11, and 10);
- engine
f4c190… at a later wall time (sequence 12).
These are distinct sends, not duplicate uploads. Grouping them by the raw string op-0 is incorrect.
Root cause
Current forensics/analysis.py:710-780 uses:
key = ("op", event.context_operation_id)
The key omits engine_id and recorder_session_id. The recorder_session_id field is already normalized on AuditEvent, but older rows may not have it.
Required behavior
- Never group a real operation ID across different
engine_id values.
- For legacy process-local IDs, include the best available runtime/session boundary in the key.
- When
recorder_session_id is absent, split conservatively on sequence resets and terminal/start boundaries rather than merging unrelated history.
- Preserve one action across audit-file reuploads/segments and recorder rotation when evidence proves continuity; do not use
audit_file_id as the logical session key.
- Export the correlation basis and an
inferred/ambiguous marker so downstream tools know whether a group is exact or heuristic.
Acceptance criteria
- Same
op-0 on two engines yields two action groups.
- Same engine +
op-0 in two runtime sessions yields two groups.
- Duplicate uploads of the same rows remain one action.
- A multi-row operation within one session remains grouped.
- Missing session metadata fails closed: separate/ambiguous groups, never silent union.
- Add a regression fixture matching the field sequence above.
Related
MDK should emit restart-safe operation/run IDs for new evidence. Goggles still needs this fix for all existing v2 exports and as defense in depth.
Problem
The group action projection merges rows solely by
context_operation_id, even though MDK operation IDs are engine-localop-Ncounters and reset after restart.As a result, unrelated actions from different participants—and separate actions from one participant after restart—can become one action card with a stretched time window, unioned message IDs, phases, and relay rows.
Field evidence
In group
26a9…, an exact export search found four distinctsend_entryrows withoperation_id = op-0:c1326c…at three separate wall times/files (sequence positions 10, 11, and 10);f4c190…at a later wall time (sequence 12).These are distinct sends, not duplicate uploads. Grouping them by the raw string
op-0is incorrect.Root cause
Current
forensics/analysis.py:710-780uses:The key omits
engine_idandrecorder_session_id. Therecorder_session_idfield is already normalized onAuditEvent, but older rows may not have it.Required behavior
engine_idvalues.recorder_session_idis absent, split conservatively on sequence resets and terminal/start boundaries rather than merging unrelated history.audit_file_idas the logical session key.inferred/ambiguousmarker so downstream tools know whether a group is exact or heuristic.Acceptance criteria
op-0on two engines yields two action groups.op-0in two runtime sessions yields two groups.Related
MDK should emit restart-safe operation/run IDs for new evidence. Goggles still needs this fix for all existing v2 exports and as defense in depth.