Split receipt transport from host execution

This commit is contained in:
Meta Vens 2026-05-22 23:25:14 +01:00
commit f0294aebd6
3 changed files with 25 additions and 12 deletions

View file

@ -1387,7 +1387,8 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
vec![RUNTIME_JOB_TYPE],
vec![
"Worker launch requests are typed task-intent documents; runtime jobs are lifecycle receipts, not the source of work intent.",
"Core/coordinator policy owns the launch yes/no; transport bridges translate, gather host facts, execute side effects, and return receipts.",
"Core/coordinator policy owns the launch yes/no; transport bridges translate and carry orders/receipts only.",
"Host executors gather host facts and perform side effects after the verdict, with readable receipts.",
],
),
mutation_contract(
@ -1598,7 +1599,7 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
vec![
"Reorientation policy is the typed resume/regather verdict surface.",
"Launch and acceptance stay review-gated through explicit typed intents.",
"The bridge may carry a reorient launch intent and report receipts, but the resume/regather verdict belongs to core.",
"The transport may carry a reorient launch intent and receipt, but the resume/regather verdict belongs to core.",
],
),
read_only_surface_contract(
@ -1620,7 +1621,7 @@ fn epiphany_mutation_contracts() -> Vec<CultNetDocumentMutationContract> {
vec![
"Job reflection over typed job bindings and runtime-spine lifecycle receipts.",
"Heartbeat/runtime-spine owns activation; callers submit typed intents and watch receipts.",
"Launch receipts must name decisionOwner and bridgeRole so transport never grows an unreadable second opinion.",
"Launch receipts must name decisionOwner, transportRole, and any hostExecutorRole so transport never grows an unreadable second opinion.",
],
),
coordinator_surface_contract(
@ -2293,16 +2294,21 @@ mod tests {
.as_array()
.expect("receipt schema should list required fields");
assert!(required.iter().any(|field| field == "decisionOwner"));
assert!(required.iter().any(|field| field == "bridgeRole"));
assert!(required.iter().any(|field| field == "transportRole"));
assert!(
receipt_schema["properties"]["decisionOwner"]["description"]
.as_str()
.is_some_and(|description| description.contains("epiphany-core"))
);
assert!(
receipt_schema["properties"]["bridgeRole"]["description"]
receipt_schema["properties"]["transportRole"]["description"]
.as_str()
.is_some_and(|description| description.contains("transport"))
.is_some_and(|description| description.contains("must not make"))
);
assert!(
receipt_schema["properties"]["hostExecutorRole"]["description"]
.as_str()
.is_some_and(|description| description.contains("gathered facts"))
);
assert!(schemas.iter().any(|schema| {
schema.document_type.as_deref() == Some(OPENAI_MODEL_REQUEST_TYPE)

View file

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.swarm-control-receipt.schema.json",
"title": "Epiphany Swarm Control Receipt",
"description": "Generic receipt emitted after a coordinator-owned Epiphany control action. The receipt names the authority that made the final yes/no decision and the transport role that carried it out.",
"description": "Generic receipt emitted after a coordinator-owned Epiphany control action. The receipt names the authority that made the final yes/no decision, the transport that carried the order, and any host executor that gathered facts or performed side effects.",
"type": "object",
"additionalProperties": true,
"properties": {
@ -22,9 +22,16 @@
"type": "string",
"description": "Authority that made the final yes/no verdict. For Epiphany-owned launch and reorientation flows this is epiphany-core, not the transport bridge."
},
"bridgeRole": {
"transportRole": {
"type": "string",
"description": "What the bridge did for this action. Expected values are transport, translate, gatherHostFacts, executeSideEffects, and reportReceipt, alone or joined with '+'."
"description": "What the transport bridge did for this action. Expected values are translate, carryOrder, carryReceipt, or a '+' joined combination. It must not make the launch/reorient verdict, gather host facts, or execute side effects."
},
"hostExecutorRole": {
"type": [
"string",
"null"
],
"description": "Host-side executor role that gathered facts or performed side effects after the core/coordinator verdict, when such an executor exists."
},
"intentDocumentType": {
"type": [
@ -88,14 +95,14 @@
},
"hostFacts": {
"type": "array",
"description": "Host/runtime facts gathered by the bridge before execution, expressed as readable labels or artifact refs rather than private context.",
"description": "Host/runtime facts gathered by the host executor before execution, expressed as readable labels or artifact refs rather than private context.",
"items": {
"type": "string"
}
},
"sideEffects": {
"type": "array",
"description": "Side effects the bridge performed after the core/coordinator verdict.",
"description": "Side effects the host executor performed after the core/coordinator verdict.",
"items": {
"type": "string"
}
@ -110,7 +117,7 @@
"action",
"authority",
"decisionOwner",
"bridgeRole",
"transportRole",
"targetDocumentType",
"status",
"summary"

Binary file not shown.