Type Epiphany launch protocol params
This commit is contained in:
parent
5886ff58ca
commit
596d5a7fb0
6 changed files with 202 additions and 32 deletions
|
|
@ -396,12 +396,16 @@ inventory and ledger now exist:
|
|||
`epiphany-core` owns `EpiphanyRoleStatePatchDocument`, policy checks read
|
||||
typed fields directly, and the app-server maps the typed document to the
|
||||
legacy `ThreadEpiphanyUpdatePatch` without JSON round-tripping.
|
||||
- Fifth cut landed: `ThreadEpiphanyJobLaunchParams` no longer exposes
|
||||
`input_json` / `output_schema_json`. The legacy app-server protocol launch
|
||||
edge now carries a typed `ThreadEpiphanyWorkerLaunchDocument` and
|
||||
`output_contract_id`, then maps that document into the native
|
||||
`EpiphanyWorkerLaunchDocument` for core.
|
||||
|
||||
Continue at the protocol edge. Replace
|
||||
`ThreadEpiphanyJobLaunchParams.input_json` / `output_schema_json` with CultNet
|
||||
typed launch-intent messages, then seal MCP JSON behind a CultNet MCP adapter.
|
||||
Do not resume Rider, Unity, Aquarium, Face, dogfood, planning, app, skill,
|
||||
marketplace, or bridge expansion until this organ is being cut cleanly.
|
||||
Continue by sealing MCP JSON behind a CultNet MCP adapter, then audit heartbeat
|
||||
cognition quarantine values for typing or explicit expiration. Do not resume
|
||||
Rider, Unity, Aquarium, Face, dogfood, planning, app, skill, marketplace, or
|
||||
bridge expansion until this organ is being cut cleanly.
|
||||
|
||||
The Phase 6 freshness slice is landed. It exposes read-only
|
||||
`thread/epiphany/freshness` from live retrieval summaries plus graph
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@ Rule: JSON is allowed at external schema/wire boundaries. Inside Epiphany, live
|
|||
- Simpler architecture: role interpretation stores `AgentSelfPatch`, and only the protocol projection serializes JSON for the existing app-server surface.
|
||||
- Files: `epiphany-core/src/agent_memory.rs`, `epiphany-core/src/surfaces/role_result.rs`, `vendor/codex/codex-rs/app-server/src/codex_message_processor.rs`, `vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs`.
|
||||
- `vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs`
|
||||
- Current mechanism: `ThreadEpiphanyRoleFinding.self_patch: Option<serde_json::Value>`, `ThreadEpiphanyJobLaunchRequest.input_json`, and `output_schema_json`.
|
||||
- Current mechanism: `ThreadEpiphanyRoleFinding.self_patch: Option<serde_json::Value>` remains for the legacy projection. Launch params now use typed worker launch documents and `output_contract_id`.
|
||||
- Real need: app-server compatibility while Epiphany is still hosted inside Codex.
|
||||
- What breaks if deleted: frontend/server protocol compilation.
|
||||
- Essential or bad ownership: temporary compatibility reliquary, not a final contract.
|
||||
- Simpler architecture: CultNet schema messages generated from typed document structs.
|
||||
- Simpler architecture: CultNet schema messages generated from typed document structs; keep app-server protocol only as a temporary compatibility reliquary.
|
||||
|
||||
## Quarantine JSON
|
||||
|
||||
|
|
@ -61,5 +61,6 @@ Rule: JSON is allowed at external schema/wire boundaries. Inside Epiphany, live
|
|||
2. Partly done: core worker launch `input_json` and `output_schema_json` are replaced by typed launch documents and output contract ids. Remaining cut is the protocol edge.
|
||||
3. Done: replace role `statePatch` JSON with typed map/planning/graph patch documents. `EpiphanyRoleFindingInterpretation` now carries `EpiphanyRoleStatePatchDocument`; app-server maps it to the legacy protocol patch without JSON round-tripping.
|
||||
4. Done: replace runtime job result JSON projections. Runtime-spine results now project through typed role/reorient interpreters instead of `runtime_job_result_to_role_json` and `runtime_job_result_to_reorient_json`.
|
||||
5. Seal MCP JSON behind a CultNet MCP adapter.
|
||||
6. Audit heartbeat cognition values and either type them or explicitly expire them.
|
||||
5. Done: replace app-server launch protocol `input_json` / `output_schema_json` with typed launch documents and `output_contract_id`.
|
||||
6. Seal MCP JSON behind a CultNet MCP adapter.
|
||||
7. Audit heartbeat cognition values and either type them or explicitly expire them.
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -278,5 +278,5 @@ rejected_paths:
|
|||
reason: making Epiphany cleaner inside Codex still preserves the wrong organ; Codex must be starved down to OpenAI subscription auth/model transport, while Epiphany data and subsystem communication move to typed CultCache/CultNet.
|
||||
|
||||
current_status:
|
||||
summary: The Codex starvation pass has four receipts. `notes/codex-auth-spine-inventory.md` maps the minimal vendored OpenAI auth/model-call spine; `notes/json-contamination-ledger.md` classifies the major Epiphany JSON uses by allowed edge, quarantine, or internal contamination. Role-result `selfPatch` and `statePatch` now use typed Epiphany documents internally. Core worker launch now uses `EpiphanyWorkerLaunchDocument` plus `output_contract_id` instead of `input_json` / `output_schema_json`. Runtime job results now project through typed role/reorient interpreters instead of JSON round-tripping. Legacy app-server JSON remains only at hostile ingress/protocol quarantine pending CultNet replacement.
|
||||
next_action: Continue the liberation pass at the protocol edge: replace `ThreadEpiphanyJobLaunchParams.input_json` / `output_schema_json` with CultNet typed launch-intent messages, then seal MCP JSON behind a CultNet MCP adapter instead of letting Codex app/tool plumbing own it.
|
||||
summary: The Codex starvation pass has five receipts. `notes/codex-auth-spine-inventory.md` maps the minimal vendored OpenAI auth/model-call spine; `notes/json-contamination-ledger.md` classifies the major Epiphany JSON uses by allowed edge, quarantine, or internal contamination. Role-result `selfPatch` and `statePatch` now use typed Epiphany documents internally. Core worker launch and app-server launch params now use typed worker launch documents plus `output_contract_id` instead of `input_json` / `output_schema_json`. Runtime job results now project through typed role/reorient interpreters instead of JSON round-tripping. Legacy app-server JSON remains in smaller compatibility pockets pending CultNet replacement.
|
||||
next_action: Continue the liberation pass by sealing MCP JSON behind a CultNet MCP adapter instead of letting Codex app/tool plumbing own it, then audit heartbeat cognition quarantine values for typing or explicit expiration.
|
||||
|
|
|
|||
|
|
@ -5492,16 +5492,118 @@ pub struct ThreadEpiphanyJobLaunchParams {
|
|||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub linked_graph_node_ids: Vec<String>,
|
||||
pub instruction: String,
|
||||
#[ts(type = "unknown")]
|
||||
pub input_json: serde_json::Value,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable, type = "unknown | null")]
|
||||
pub output_schema_json: Option<serde_json::Value>,
|
||||
pub launch_document: ThreadEpiphanyWorkerLaunchDocument,
|
||||
pub output_contract_id: String,
|
||||
#[serde(default)]
|
||||
#[ts(optional = nullable)]
|
||||
pub max_runtime_seconds: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase", tag = "documentKind")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub enum ThreadEpiphanyWorkerLaunchDocument {
|
||||
Role(ThreadEpiphanyRoleWorkerLaunchDocument),
|
||||
Reorient(ThreadEpiphanyReorientWorkerLaunchDocument),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadEpiphanyRoleWorkerLaunchDocument {
|
||||
pub thread_id: String,
|
||||
pub role_id: String,
|
||||
pub state_revision: u64,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub objective: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub active_subgoal_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub active_subgoals: Vec<CoreEpiphanySubgoal>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub active_graph_node_ids: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub investigation_checkpoint: Option<CoreEpiphanyInvestigationCheckpoint>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub scratch: Option<CoreEpiphanyScratchPad>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub invariants: Vec<CoreEpiphanyInvariant>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub graphs: Option<CoreEpiphanyGraphs>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub recent_evidence: Vec<CoreEpiphanyEvidenceRecord>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub recent_observations: Vec<CoreEpiphanyObservation>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub graph_frontier: Option<CoreEpiphanyGraphFrontier>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub graph_checkpoint: Option<CoreEpiphanyGraphCheckpoint>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub planning: Option<CoreEpiphanyPlanningState>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub churn: Option<CoreEpiphanyChurnState>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadEpiphanyReorientWorkerLaunchDocument {
|
||||
pub thread_id: String,
|
||||
pub mode: String,
|
||||
pub checkpoint_id: String,
|
||||
pub checkpoint_kind: String,
|
||||
pub checkpoint_disposition: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub checkpoint_focus: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub checkpoint_summary: Option<String>,
|
||||
pub checkpoint_next_action: String,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub checkpoint_open_questions: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub checkpoint_evidence_ids: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub checkpoint_code_refs: Vec<CoreEpiphanyCodeRef>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub decision_reasons: Vec<String>,
|
||||
pub decision_note: String,
|
||||
pub pressure_level: String,
|
||||
pub retrieval_status: String,
|
||||
pub graph_status: String,
|
||||
pub watcher_status: String,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub checkpoint_dirty_paths: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub checkpoint_changed_paths: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub scratch: Option<CoreEpiphanyScratchPad>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional = nullable)]
|
||||
pub graphs: Option<CoreEpiphanyGraphs>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub recent_evidence: Vec<CoreEpiphanyEvidenceRecord>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub recent_observations: Vec<CoreEpiphanyObservation>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub active_frontier_node_ids: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub linked_subgoal_ids: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub linked_graph_node_ids: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ use codex_app_server_protocol::ThreadEpiphanyReorientResultResponse;
|
|||
use codex_app_server_protocol::ThreadEpiphanyReorientResultStatus;
|
||||
use codex_app_server_protocol::ThreadEpiphanyReorientSource;
|
||||
use codex_app_server_protocol::ThreadEpiphanyReorientStateStatus;
|
||||
use codex_app_server_protocol::ThreadEpiphanyReorientWorkerLaunchDocument;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRetrievalFreshness;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRetrievalFreshnessStatus;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRetrieveIndexSummary;
|
||||
|
|
@ -228,6 +229,7 @@ use codex_app_server_protocol::ThreadEpiphanyRoleResultStatus;
|
|||
use codex_app_server_protocol::ThreadEpiphanyRoleSelfPersistenceReview;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRoleSelfPersistenceStatus;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRoleStatus;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRoleWorkerLaunchDocument;
|
||||
use codex_app_server_protocol::ThreadEpiphanyRolesSource;
|
||||
use codex_app_server_protocol::ThreadEpiphanyScene;
|
||||
use codex_app_server_protocol::ThreadEpiphanySceneAction;
|
||||
|
|
@ -255,6 +257,7 @@ use codex_app_server_protocol::ThreadEpiphanyViewPlanning;
|
|||
use codex_app_server_protocol::ThreadEpiphanyViewReorient;
|
||||
use codex_app_server_protocol::ThreadEpiphanyViewResponse;
|
||||
use codex_app_server_protocol::ThreadEpiphanyViewRoles;
|
||||
use codex_app_server_protocol::ThreadEpiphanyWorkerLaunchDocument;
|
||||
use codex_app_server_protocol::ThreadForkParams;
|
||||
use codex_app_server_protocol::ThreadForkResponse;
|
||||
use codex_app_server_protocol::ThreadIncrementElicitationParams;
|
||||
|
|
@ -6385,8 +6388,8 @@ impl CodexMessageProcessor {
|
|||
linked_subgoal_ids,
|
||||
linked_graph_node_ids,
|
||||
instruction,
|
||||
input_json,
|
||||
output_schema_json: _,
|
||||
launch_document,
|
||||
output_contract_id,
|
||||
max_runtime_seconds,
|
||||
} = params;
|
||||
|
||||
|
|
@ -6411,19 +6414,7 @@ impl CodexMessageProcessor {
|
|||
}
|
||||
};
|
||||
|
||||
let launch_document =
|
||||
match serde_json::from_value::<EpiphanyWorkerLaunchDocument>(input_json) {
|
||||
Ok(document) => document,
|
||||
Err(err) => {
|
||||
self.send_invalid_request_error(
|
||||
request_id,
|
||||
format!("invalid Epiphany job launch document: {err}"),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
let output_contract_id = launch_document.output_contract_id().to_string();
|
||||
let launch_document = map_core_worker_launch_document(launch_document);
|
||||
let changed_fields = epiphany_job_launch_changed_fields();
|
||||
let launched = match thread
|
||||
.epiphany_launch_job(EpiphanyJobLaunchRequest {
|
||||
|
|
@ -13412,6 +13403,78 @@ fn map_protocol_update_patch(patch: EpiphanyRoleStatePatchDocument) -> ThreadEpi
|
|||
}
|
||||
}
|
||||
|
||||
fn map_core_worker_launch_document(
|
||||
document: ThreadEpiphanyWorkerLaunchDocument,
|
||||
) -> EpiphanyWorkerLaunchDocument {
|
||||
match document {
|
||||
ThreadEpiphanyWorkerLaunchDocument::Role(document) => {
|
||||
EpiphanyWorkerLaunchDocument::Role(map_core_role_worker_launch_document(document))
|
||||
}
|
||||
ThreadEpiphanyWorkerLaunchDocument::Reorient(document) => {
|
||||
EpiphanyWorkerLaunchDocument::Reorient(map_core_reorient_worker_launch_document(
|
||||
document,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn map_core_role_worker_launch_document(
|
||||
document: ThreadEpiphanyRoleWorkerLaunchDocument,
|
||||
) -> EpiphanyRoleWorkerLaunchDocument {
|
||||
EpiphanyRoleWorkerLaunchDocument {
|
||||
thread_id: document.thread_id,
|
||||
role_id: document.role_id,
|
||||
state_revision: document.state_revision,
|
||||
objective: document.objective,
|
||||
active_subgoal_id: document.active_subgoal_id,
|
||||
active_subgoals: document.active_subgoals,
|
||||
active_graph_node_ids: document.active_graph_node_ids,
|
||||
investigation_checkpoint: document.investigation_checkpoint,
|
||||
scratch: document.scratch,
|
||||
invariants: document.invariants,
|
||||
graphs: document.graphs,
|
||||
recent_evidence: document.recent_evidence,
|
||||
recent_observations: document.recent_observations,
|
||||
graph_frontier: document.graph_frontier,
|
||||
graph_checkpoint: document.graph_checkpoint,
|
||||
planning: document.planning,
|
||||
churn: document.churn,
|
||||
}
|
||||
}
|
||||
|
||||
fn map_core_reorient_worker_launch_document(
|
||||
document: ThreadEpiphanyReorientWorkerLaunchDocument,
|
||||
) -> EpiphanyReorientWorkerLaunchDocument {
|
||||
EpiphanyReorientWorkerLaunchDocument {
|
||||
thread_id: document.thread_id,
|
||||
mode: document.mode,
|
||||
checkpoint_id: document.checkpoint_id,
|
||||
checkpoint_kind: document.checkpoint_kind,
|
||||
checkpoint_disposition: document.checkpoint_disposition,
|
||||
checkpoint_focus: document.checkpoint_focus,
|
||||
checkpoint_summary: document.checkpoint_summary,
|
||||
checkpoint_next_action: document.checkpoint_next_action,
|
||||
checkpoint_open_questions: document.checkpoint_open_questions,
|
||||
checkpoint_evidence_ids: document.checkpoint_evidence_ids,
|
||||
checkpoint_code_refs: document.checkpoint_code_refs,
|
||||
decision_reasons: document.decision_reasons,
|
||||
decision_note: document.decision_note,
|
||||
pressure_level: document.pressure_level,
|
||||
retrieval_status: document.retrieval_status,
|
||||
graph_status: document.graph_status,
|
||||
watcher_status: document.watcher_status,
|
||||
checkpoint_dirty_paths: document.checkpoint_dirty_paths,
|
||||
checkpoint_changed_paths: document.checkpoint_changed_paths,
|
||||
scratch: document.scratch,
|
||||
graphs: document.graphs,
|
||||
recent_evidence: document.recent_evidence,
|
||||
recent_observations: document.recent_observations,
|
||||
active_frontier_node_ids: document.active_frontier_node_ids,
|
||||
linked_subgoal_ids: document.linked_subgoal_ids,
|
||||
linked_graph_node_ids: document.linked_graph_node_ids,
|
||||
}
|
||||
}
|
||||
|
||||
fn core_state_patch_from_protocol(
|
||||
patch: &ThreadEpiphanyUpdatePatch,
|
||||
) -> EpiphanyRoleStatePatchDocument {
|
||||
|
|
|
|||
Reference in a new issue