diff --git a/agent99-control-plane.ps1 b/agent99-control-plane.ps1 index 3226cbdc5..fb342cb5a 100644 --- a/agent99-control-plane.ps1 +++ b/agent99-control-plane.ps1 @@ -5643,6 +5643,11 @@ function Invoke-AgentCompletionCallback { $alertId = [string](Get-AgentObjectValue $Result "alertId" "") $callbackIncidentId = Get-AgentCompletionCallbackIncidentId $Result $alertId $correlationKey = [string](Get-AgentObjectValue $Result "correlationKey" "") + $identity = Get-AgentObjectValue $Result "identity" $null + $canonicalProjectId = [string](Get-AgentObjectValue $identity "project_id" "") + $canonicalRunId = [string](Get-AgentObjectValue $identity "run_id" "") + $canonicalTraceId = [string](Get-AgentObjectValue $identity "trace_id" "") + $canonicalWorkItemId = [string](Get-AgentObjectValue $identity "work_item_id" "") $callbackId = Convert-AgentSafeKey "agent99:$resultId`:$outcomeState" $evidencePath = [string](Get-AgentObjectValue $Result "evidence" "") $visualPath = [string](Get-AgentObjectValue $TelegramAttempt "visualPath" "") @@ -5650,10 +5655,10 @@ function Invoke-AgentCompletionCallback { $payload = [ordered]@{ schema_version = "agent99_completion_callback_v1" callback_id = $callbackId - project_id = "awoooi" - run_id = $resultId - trace_id = if ($correlationKey) { $correlationKey } else { $resultId } - work_item_id = if ($alertId) { "agent99-incident:$alertId" } else { "agent99-command:$resultId" } + project_id = if ($canonicalProjectId) { $canonicalProjectId } else { "awoooi" } + run_id = if ($canonicalRunId) { $canonicalRunId } else { $resultId } + trace_id = if ($canonicalTraceId) { $canonicalTraceId } elseif ($correlationKey) { $correlationKey } else { $resultId } + work_item_id = if ($canonicalWorkItemId) { $canonicalWorkItemId } elseif ($alertId) { "agent99-incident:$alertId" } else { "agent99-command:$resultId" } alert_id = $callbackIncidentId correlation_key = if ($correlationKey) { $correlationKey } else { $null } source = [string](Get-AgentObjectValue $Result "source" "agent99") diff --git a/apps/api/tests/test_agent99_control_plane_outcome_contract.py b/apps/api/tests/test_agent99_control_plane_outcome_contract.py index 249860762..7f18c6a94 100644 --- a/apps/api/tests/test_agent99_control_plane_outcome_contract.py +++ b/apps/api/tests/test_agent99_control_plane_outcome_contract.py @@ -150,6 +150,19 @@ def test_agent99_completion_callback_uses_bounded_canonical_incident_id() -> Non assert "alert_id = if ($alertId)" not in source +def test_agent99_completion_callback_preserves_canonical_execution_identity() -> None: + source = _CONTROL_PLANE.read_text(encoding="utf-8") + + assert '$identity = Get-AgentObjectValue $Result "identity" $null' in source + assert 'Get-AgentObjectValue $identity "project_id" ""' in source + assert 'Get-AgentObjectValue $identity "run_id" ""' in source + assert 'Get-AgentObjectValue $identity "trace_id" ""' in source + assert 'Get-AgentObjectValue $identity "work_item_id" ""' in source + assert "run_id = if ($canonicalRunId)" in source + assert "trace_id = if ($canonicalTraceId)" in source + assert "work_item_id = if ($canonicalWorkItemId)" in source + + def test_agent99_backupcheck_reads_offsite_and_escrow_without_mutation() -> None: source = _CONTROL_PLANE.read_text(encoding="utf-8") readback = source[