fix(runner): record the resumed semantic result

Require the control plane's canonical result receipt and emit it once after durable completion. The live qualifier now reconciles semantic input, result, provider usage, and the final control-plane effect.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-26 20:02:08 +00:00
1 parent 7a2a136565
commit fe3264fb49
3 files changed
+60 -6

No files matched your search

@@ -807,6 +807,22 @@ impl CodexCommandExecutor {
.ok_or_else(|| {
DurableRunnerError::invalid("semantic_tool.result has no pending call")
})?;
let result_receipt = result
.get("resultReceipt")
.filter(|receipt| {
receipt.get("schema").and_then(Value::as_str)
== Some("paperclip.prp.semantic_tool.v1")
&& receipt.get("phase").and_then(Value::as_str) == Some("result")
&& receipt.get("callId").and_then(Value::as_str) == Some(call_id)
&& receipt.get("operationId").and_then(Value::as_str)
== Some(pending.operation_id.as_str())
})
.cloned()
.ok_or_else(|| {
DurableRunnerError::invalid(
"semantic_tool.result requires its matching canonical resultReceipt",
)
})?;
let state = self
.state
.as_mut()
@@ -838,10 +854,17 @@ impl CodexCommandExecutor {
} else {
false
};
Ok(CommandExecution::result(json!({
"status": if delivered { "delivered" } else { "deferred" },
"callId": call_id,
})))
Ok(CommandExecution {
result: json!({
"status": if delivered { "delivered" } else { "deferred" },
"callId": call_id,
}),
events: vec![(
"semantic_tool.result".to_owned(),
EventPriority::P0,
json!({"semantic_tool": result_receipt}),
)],
})
}
fn close_session(&mut self) -> Result<CommandExecution, DurableRunnerError> {
@@ -254,7 +254,34 @@ fn durable_backend_resumes_one_pending_native_tool_call_with_the_same_identity()
"semantic_tool.result",
json!({
"callId": "semantic-call-1",
"result": {"ok": true, "value": {"task": "NCV-1"}},
"result": {
"ok": true,
"value": {"task": "NCV-1"},
"resultReceipt": {
"schema": "paperclip.prp.semantic_tool.v1",
"schemaVersion": 1,
"phase": "result",
"operationId": "report_progress",
"callId": "semantic-call-1",
"correlation": {
"runId": "run-1",
"normalizedSessionId": "session-1",
"turnId": "turn-1",
"itemId": "item-1"
},
"idempotencyKey": "native-resume-proof-1",
"content": {
"digest": format!("sha256:{}", "a".repeat(64)),
"redactionDisposition": "digest_only",
"references": []
},
"outcome": "succeeded",
"code": "ok",
"retryable": false,
"authorizationBoundary": "active_task",
"operationReceiptId": "receipt-1"
}
},
"isError": false,
}),
))
@@ -334,6 +334,10 @@ describeEmbeddedPostgres("native Codex server vertical slice", () => {
]);
if (liveCodex) {
const usageReports = nativeEvents
.filter((event) => event.eventType === "usage.reported")
.map((event) => event.payload?.prpEvent)
.filter((event): event is Record<string, unknown> => Boolean(event));
console.log("NATIVE_CODEX_RESUME_PROOF", JSON.stringify({
appCommit: process.env.PAPERCLIP_LIVE_CODEX_APP_COMMIT ?? null,
runId,
@@ -349,7 +353,7 @@ describeEmbeddedPostgres("native Codex server vertical slice", () => {
(event) => event.eventType === "semantic_tool.result",
).length,
controlPlaneEffectCount: progressEffects.length,
usage: result.usage ?? null,
usageReports,
}));
return;
}