2026-05-28 21:02:26 +01:00
use std ::sync ::OnceLock ;
use crate ::EpiphanyCoordinatorAction as CoreEpiphanyCoordinatorAction ;
use crate ::EpiphanyCoordinatorRoleResultStatus as CoreEpiphanyCoordinatorRoleResultStatus ;
use crate ::EpiphanyCrrcAction as CoreEpiphanyCrrcAction ;
use crate ::EpiphanyCrrcResultStatus as CoreEpiphanyCrrcResultStatus ;
use crate ::EpiphanyJobLaunchRequest ;
use crate ::EpiphanyPressure ;
use crate ::EpiphanyPressureLevel as CoreEpiphanyPressureLevel ;
use crate ::EpiphanyReorientAction as CoreEpiphanyReorientAction ;
use crate ::EpiphanyRoleResultRoleId ;
use crate ::EpiphanyRoleWorkerLaunchDocument ;
use crate ::EpiphanyWorkerLaunchDocument ;
2026-08-13 22:14:56 +02:00
use crate ::default_launch_organ_contract ;
2026-05-28 21:02:26 +01:00
use epiphany_state_model ::EpiphanyJobKind as CoreEpiphanyJobKind ;
use epiphany_state_model ::EpiphanyThreadState ;
pub const EPIPHANY_IMAGINATION_ROLE_BINDING_ID : & str = " planning-synthesis-worker " ;
pub const EPIPHANY_IMAGINATION_OWNER_ROLE : & str = " epiphany-imagination " ;
2026-07-15 03:05:11 +01:00
pub const EPIPHANY_MIND_ROLE_BINDING_ID : & str = " mind-admission-reviewer " ;
pub const EPIPHANY_MIND_OWNER_ROLE : & str = " epiphany-mind-admission-review " ;
2026-05-30 01:02:16 +01:00
pub const EPIPHANY_RESEARCH_ROLE_BINDING_ID : & str = " research-source-gather-worker " ;
pub const EPIPHANY_RESEARCH_OWNER_ROLE : & str = " epiphany-eyes " ;
2026-05-28 21:02:26 +01:00
pub const EPIPHANY_MODELING_ROLE_BINDING_ID : & str = " modeling-checkpoint-worker " ;
pub const EPIPHANY_MODELING_OWNER_ROLE : & str = " epiphany-modeler " ;
pub const EPIPHANY_VERIFICATION_ROLE_BINDING_ID : & str = " verification-review-worker " ;
pub const EPIPHANY_VERIFICATION_OWNER_ROLE : & str = " epiphany-verifier " ;
pub const EPIPHANY_REORIENT_LAUNCH_BINDING_ID : & str = " reorient-worker " ;
pub const EPIPHANY_REORIENT_OWNER_ROLE : & str = " epiphany-reorient " ;
pub fn epiphany_role_binding_id ( role_id : EpiphanyRoleResultRoleId ) -> Result < & 'static str , String > {
match role_id {
EpiphanyRoleResultRoleId ::Imagination = > Ok ( EPIPHANY_IMAGINATION_ROLE_BINDING_ID ) ,
2026-05-30 01:02:16 +01:00
EpiphanyRoleResultRoleId ::Research = > Ok ( EPIPHANY_RESEARCH_ROLE_BINDING_ID ) ,
2026-05-28 21:02:26 +01:00
EpiphanyRoleResultRoleId ::Modeling = > Ok ( EPIPHANY_MODELING_ROLE_BINDING_ID ) ,
EpiphanyRoleResultRoleId ::Verification = > Ok ( EPIPHANY_VERIFICATION_ROLE_BINDING_ID ) ,
EpiphanyRoleResultRoleId ::Implementation = > Err (
" implementation is owned by the main coding agent; no role specialist launch template exists "
. to_string ( ) ,
) ,
EpiphanyRoleResultRoleId ::Reorientation = > Err (
2026-07-12 00:41:05 +01:00
" reorientation uses epiphany.coordinator.reorient.launch and epiphany.coordinator.reorient.result.read "
2026-05-28 21:02:26 +01:00
. to_string ( ) ,
) ,
}
}
pub fn epiphany_role_owner ( role_id : EpiphanyRoleResultRoleId ) -> Result < & 'static str , String > {
match role_id {
EpiphanyRoleResultRoleId ::Imagination = > Ok ( EPIPHANY_IMAGINATION_OWNER_ROLE ) ,
2026-05-30 01:02:16 +01:00
EpiphanyRoleResultRoleId ::Research = > Ok ( EPIPHANY_RESEARCH_OWNER_ROLE ) ,
2026-05-28 21:02:26 +01:00
EpiphanyRoleResultRoleId ::Modeling = > Ok ( EPIPHANY_MODELING_OWNER_ROLE ) ,
EpiphanyRoleResultRoleId ::Verification = > Ok ( EPIPHANY_VERIFICATION_OWNER_ROLE ) ,
EpiphanyRoleResultRoleId ::Implementation | EpiphanyRoleResultRoleId ::Reorientation = > {
Err ( epiphany_role_binding_id ( role_id ) . unwrap_err ( ) )
}
}
}
pub fn epiphany_role_label ( role_id : EpiphanyRoleResultRoleId ) -> & 'static str {
match role_id {
EpiphanyRoleResultRoleId ::Implementation = > " implementation " ,
EpiphanyRoleResultRoleId ::Imagination = > " imagination " ,
2026-05-30 01:02:16 +01:00
EpiphanyRoleResultRoleId ::Research = > " research " ,
2026-05-28 21:02:26 +01:00
EpiphanyRoleResultRoleId ::Modeling = > " modeling " ,
EpiphanyRoleResultRoleId ::Verification = > " verification " ,
EpiphanyRoleResultRoleId ::Reorientation = > " reorientation " ,
}
}
2026-07-16 16:49:45 +01:00
fn repo_frontier_item_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
2026-08-07 02:09:43 +01:00
" required " : [ " id " , " migration_body " , " question " , " gap " , " target_claim_ids " , " recommended_next_organ " , " status " ] ,
2026-07-16 16:49:45 +01:00
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" migration_body " : { " type " : " string " , " minLength " : 1 } ,
" question " : { " type " : " string " , " minLength " : 1 } ,
" gap " : { " type " : " string " , " minLength " : 1 } ,
2026-08-07 02:09:43 +01:00
" target_claim_ids " : { " type " : " array " , " minItems " : 1 , " items " : { " type " : " string " , " minLength " : 1 } } ,
2026-07-16 16:49:45 +01:00
" source_scope " : { " type " : " array " , " items " : { " type " : " string " } } ,
" recommended_next_organ " : { " type " : " string " , " minLength " : 1 } ,
" dependency_item_ids " : { " type " : " array " , " items " : { " type " : " string " } } ,
" status " : { " type " : " string " , " enum " : [ " proposed " , " active " , " blocked " , " resolved " , " retired " , " superseded " ] } ,
2026-08-14 16:19:35 +02:00
" evidence_refs " : { " type " : " array " , " items " : { " type " : " string " } }
2026-07-16 16:49:45 +01:00
}
} )
}
fn repo_model_node_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " id " , " domain_id " , " profile " , " kind " , " title " , " claim " , " question " , " tension " , " action_implication " ] ,
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" domain_id " : { " type " : " string " , " minLength " : 1 } ,
" profile " : { " type " : " string " , " enum " : [ " repo_architecture " , " repo_dataflow " , " role_self " , " short_term " , " incubation " , " agency_pressure " , " candidate_intervention " , " identity " , " evidence " ] } ,
" kind " : { " type " : " string " , " enum " : [ " domain " , " module " , " crate " , " binary " , " schema " , " runtime_contract " , " adapter " , " test_seam " , " state_store " , " role_memory " , " short_term_thought " , " incubation_thread " , " agency_pressure " , " candidate_intervention " , " identity " , " evidence " , " summary " , " other " ] } ,
2026-08-06 23:59:40 +01:00
" title " : { " type " : " string " , " minLength " : 1 } ,
" claim " : { " type " : " string " , " minLength " : 1 } ,
2026-07-16 16:49:45 +01:00
" question " : { " type " : " string " } ,
" tension " : { " type " : " string " } ,
2026-08-06 23:59:40 +01:00
" action_implication " : { " type " : " string " , " minLength " : 1 } ,
2026-07-16 16:49:45 +01:00
" anchors " : { " type " : " array " , " items " : memory_anchor_output_schema ( ) } ,
" source_hashes " : { " type " : " array " , " items " : { " type " : " string " } } ,
" lifecycle " : { " type " : " string " } ,
" salience " : { " type " : " integer " , " minimum " : 0 } ,
2026-08-14 16:19:35 +02:00
" confidence " : { " type " : " integer " , " minimum " : 0 }
2026-07-16 16:49:45 +01:00
} ,
2026-08-06 23:59:40 +01:00
" anyOf " : [
{ " properties " : { " question " : { " minLength " : 1 } } } ,
{ " properties " : { " tension " : { " minLength " : 1 } } }
] ,
2026-07-16 16:49:45 +01:00
" additionalProperties " : false
} )
}
fn repo_model_edge_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " id " , " source_id " , " target_id " , " kind " , " profile " , " claim " ] ,
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" source_id " : { " type " : " string " , " minLength " : 1 } ,
" target_id " : { " type " : " string " , " minLength " : 1 } ,
" kind " : { " type " : " string " , " enum " : [ " owns " , " reads " , " writes " , " derives " , " adapts " , " persists " , " launches " , " verifies " , " supports " , " contradicts " , " distills " , " revises " , " retires " , " grounds " , " triggers " , " spoken_as " , " cools " , " clusters_with " , " resonates_with " , " depends_on " , " other " ] } ,
" profile " : { " type " : " string " , " enum " : [ " repo_architecture " , " repo_dataflow " , " role_self " , " short_term " , " incubation " , " agency_pressure " , " candidate_intervention " , " identity " , " evidence " ] } ,
" claim " : { " type " : " string " } ,
" anchors " : { " type " : " array " , " items " : memory_anchor_output_schema ( ) } ,
" lifecycle " : { " type " : " string " } ,
" confidence " : { " type " : " integer " , " minimum " : 0 }
} ,
" additionalProperties " : false
} )
}
2026-08-14 17:24:25 +02:00
fn atlas_repository_identity_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " swarm_id " , " workspace_id " , " repository_uri " ] ,
" properties " : {
" swarm_id " : { " type " : " string " , " minLength " : 1 } ,
" workspace_id " : { " type " : " string " , " minLength " : 1 } ,
" repository_uri " : { " type " : " string " , " pattern " : " ^gamecult://swarm/[^/]+/workspace/[^/]+$ " }
} ,
" additionalProperties " : false
} )
}
fn atlas_contract_descriptor_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" anyOf " : [
{
" type " : " object " ,
" required " : [ " version_scheme " , " contract_id " , " version " ] ,
" properties " : {
" version_scheme " : { " const " : " semver " } ,
" contract_id " : { " type " : " string " , " minLength " : 1 } ,
" version " : { " type " : " string " , " minLength " : 1 }
} ,
" additionalProperties " : false
} ,
{
" type " : " object " ,
" required " : [ " version_scheme " , " contract_id " , " schema_id " ] ,
" properties " : {
" version_scheme " : { " const " : " exact_schema " } ,
" contract_id " : { " type " : " string " , " minLength " : 1 } ,
" schema_id " : { " type " : " string " , " minLength " : 1 }
} ,
" additionalProperties " : false
} ,
{
" type " : " object " ,
" required " : [ " version_scheme " , " contract_id " , " sha256 " ] ,
" properties " : {
" version_scheme " : { " const " : " exact_digest " } ,
" contract_id " : { " type " : " string " , " minLength " : 1 } ,
" sha256 " : { " type " : " string " , " pattern " : " ^sha256-[0-9a-f]{64}$ " }
} ,
" additionalProperties " : false
}
]
} )
}
fn atlas_contract_requirement_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" anyOf " : [
{
" type " : " object " ,
" required " : [ " version_scheme " , " contract_id " , " requirement " ] ,
" properties " : {
" version_scheme " : { " const " : " semver " } ,
" contract_id " : { " type " : " string " , " minLength " : 1 } ,
" requirement " : { " type " : " string " , " minLength " : 1 }
} ,
" additionalProperties " : false
} ,
{
" type " : " object " ,
" required " : [ " version_scheme " , " contract_id " , " schema_id " ] ,
" properties " : {
" version_scheme " : { " const " : " exact_schema " } ,
" contract_id " : { " type " : " string " , " minLength " : 1 } ,
" schema_id " : { " type " : " string " , " minLength " : 1 }
} ,
" additionalProperties " : false
} ,
{
" type " : " object " ,
" required " : [ " version_scheme " , " contract_id " , " sha256 " ] ,
" properties " : {
" version_scheme " : { " const " : " exact_digest " } ,
" contract_id " : { " type " : " string " , " minLength " : 1 } ,
" sha256 " : { " type " : " string " , " pattern " : " ^sha256-[0-9a-f]{64}$ " }
} ,
" additionalProperties " : false
}
]
} )
}
fn atlas_dependency_target_output_schema ( ) -> serde_json ::Value {
let requirement = atlas_contract_requirement_output_schema ( ) ;
serde_json ::json! ( {
" anyOf " : [
{
" type " : " object " ,
" required " : [ " resolution " , " provider " , " surface_id " , " requirement " ] ,
" properties " : {
" resolution " : { " const " : " exact " } ,
" provider " : atlas_repository_identity_output_schema ( ) ,
" surface_id " : { " type " : " string " , " format " : " uuid " } ,
" requirement " : requirement . clone ( )
} ,
" additionalProperties " : false
} ,
{
" type " : " object " ,
" required " : [ " resolution " , " requirement " ] ,
" properties " : {
" resolution " : { " const " : " unresolved " } ,
" requirement " : requirement
} ,
" additionalProperties " : false
}
]
} )
}
fn atlas_impact_scope_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" anyOf " : [
{
" type " : " object " ,
" required " : [ " scope " ] ,
" properties " : { " scope " : { " const " : " whole_repository " } } ,
" additionalProperties " : false
} ,
{
" type " : " object " ,
" required " : [ " scope " , " surface_ids " ] ,
" properties " : {
" scope " : { " const " : " local_surfaces " } ,
" surface_ids " : {
" type " : " array " ,
" minItems " : 1 ,
" uniqueItems " : true ,
" items " : { " type " : " string " , " format " : " uuid " }
}
} ,
" additionalProperties " : false
}
]
} )
}
2026-07-16 16:49:45 +01:00
fn code_ref_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " path " ] ,
" properties " : {
" path " : { " type " : " string " , " minLength " : 1 } ,
" start_line " : { " type " : " integer " , " minimum " : 1 } ,
" end_line " : { " type " : " integer " , " minimum " : 1 } ,
" symbol " : { " type " : " string " } ,
" note " : { " type " : " string " }
} ,
" additionalProperties " : false
} )
}
fn memory_anchor_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " id " , " kind " , " target " ] ,
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" kind " : { " type " : " string " , " minLength " : 1 } ,
" target " : { " type " : " string " , " minLength " : 1 } ,
" code_ref " : code_ref_output_schema ( ) ,
" evidence_id " : { " type " : " string " } ,
" source_hash " : { " type " : " string " }
} ,
" additionalProperties " : false
} )
}
fn observation_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " id " , " summary " , " source_kind " , " status " ] ,
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" source_kind " : { " type " : " string " , " minLength " : 1 } ,
" status " : { " type " : " string " , " minLength " : 1 } ,
" code_refs " : { " type " : " array " , " items " : code_ref_output_schema ( ) } ,
" evidence_ids " : { " type " : " array " , " items " : { " type " : " string " } }
} ,
" additionalProperties " : false
} )
}
fn evidence_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " id " , " kind " , " status " , " summary " ] ,
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" kind " : { " type " : " string " , " minLength " : 1 } ,
" status " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" code_refs " : { " type " : " array " , " items " : code_ref_output_schema ( ) }
} ,
" additionalProperties " : false
} )
}
2026-08-13 22:14:56 +02:00
fn investigation_checkpoint_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" description " : " Outer statePatch uses camelCase; this typed checkpoint payload uses its canonical snake_case field names. " ,
" required " : [ " checkpoint_id " , " kind " , " disposition " , " focus " ] ,
" properties " : {
" checkpoint_id " : { " type " : " string " , " minLength " : 1 } ,
" kind " : { " type " : " string " , " minLength " : 1 } ,
" disposition " : { " type " : " string " , " enum " : [ " resume_ready " , " regather_required " ] } ,
" focus " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " } ,
" next_action " : { " type " : " string " } ,
" captured_at_turn_id " : { " type " : " string " } ,
" open_questions " : { " type " : " array " , " items " : { " type " : " string " } } ,
" code_refs " : { " type " : " array " , " items " : code_ref_output_schema ( ) } ,
" evidence_ids " : { " type " : " array " , " items " : { " type " : " string " } }
} ,
" additionalProperties " : false
} )
}
fn objective_draft_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " id " , " title " , " summary " , " scope " , " acceptance_criteria " , " lane_plan " , " status " ] ,
" properties " : {
" id " : { " type " : " string " , " minLength " : 1 } ,
" title " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" source_item_ids " : { " type " : " array " , " items " : { " type " : " string " } } ,
" scope " : {
" type " : " object " ,
" properties " : {
" includes " : { " type " : " array " , " items " : { " type " : " string " } } ,
" excludes " : { " type " : " array " , " items " : { " type " : " string " } }
} ,
" additionalProperties " : false
} ,
" acceptance_criteria " : { " type " : " array " , " minItems " : 1 , " items " : { " type " : " string " , " minLength " : 1 } } ,
" evidence_required " : { " type " : " array " , " items " : { " type " : " string " } } ,
" lane_plan " : {
" type " : " object " ,
" properties " : {
" imagination " : { " type " : " string " } ,
" eyes " : { " type " : " string " } ,
" body " : { " type " : " string " } ,
" hands " : { " type " : " string " } ,
" soul " : { " type " : " string " } ,
" life " : { " type " : " string " }
} ,
" additionalProperties " : false
} ,
" dependencies " : { " type " : " array " , " items " : { " type " : " string " } } ,
" risks " : { " type " : " array " , " items " : { " type " : " string " } } ,
" review_gates " : { " type " : " array " , " items " : { " type " : " string " } } ,
" status " : { " type " : " string " , " enum " : [ " draft " ] }
} ,
" additionalProperties " : false
} )
}
2026-08-07 05:21:32 +01:00
fn self_patch_memory_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " memoryId " , " summary " , " salience " , " confidence " ] ,
" properties " : {
" memoryId " : { " type " : " string " } ,
" summary " : { " type " : " string " , " minLength " : 1 , " maxLength " : 600 } ,
" salience " : { " type " : " number " , " minimum " : 0 , " maximum " : 1 } ,
" confidence " : { " type " : " number " , " minimum " : 0 , " maximum " : 1 } ,
" linkedEventIds " : { " type " : " array " , " items " : { " type " : " string " } } ,
" linkedRelationshipId " : { " type " : " string " }
} ,
" additionalProperties " : false
} )
}
fn self_patch_goal_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " goalId " , " description " , " scope " , " priority " , " emotionalStake " , " status " ] ,
" properties " : {
" goalId " : { " type " : " string " } ,
" description " : { " type " : " string " , " minLength " : 1 , " maxLength " : 700 } ,
" scope " : { " type " : " string " , " enum " : [ " immediate " , " scene " , " case " , " arc " , " life " ] } ,
" priority " : { " type " : " number " , " minimum " : 0 , " maximum " : 1 } ,
" emotionalStake " : { " type " : " string " , " minLength " : 1 , " maxLength " : 400 } ,
" blockers " : { " type " : " array " , " items " : { " type " : " string " } } ,
" status " : { " type " : " string " , " enum " : [ " active " , " blocked " , " dormant " , " resolved " , " abandoned " ] }
} ,
" additionalProperties " : false
} )
}
fn self_patch_value_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" required " : [ " valueId " , " label " , " priority " , " unforgivableIfBetrayed " ] ,
" properties " : {
" valueId " : { " type " : " string " } ,
" label " : { " type " : " string " , " minLength " : 1 , " maxLength " : 240 } ,
" priority " : { " type " : " number " , " minimum " : 0 , " maximum " : 1 } ,
" unforgivableIfBetrayed " : { " type " : " boolean " }
} ,
" additionalProperties " : false
} )
}
2026-05-28 21:02:26 +01:00
pub fn epiphany_role_launch_output_schema ( role_id : EpiphanyRoleResultRoleId ) -> serde_json ::Value {
let verdict_enum = match role_id {
EpiphanyRoleResultRoleId ::Imagination = > {
vec! [ " draft-ready " , " planning-update-needed " , " blocked " ]
}
2026-05-30 01:02:16 +01:00
EpiphanyRoleResultRoleId ::Research = > {
vec! [ " evidence-ready " , " source-gap " , " blocked " ]
}
2026-05-28 21:02:26 +01:00
EpiphanyRoleResultRoleId ::Modeling = > {
vec! [
" checkpoint-ready " ,
" checkpoint-update-needed " ,
" regather-needed " ,
]
}
EpiphanyRoleResultRoleId ::Verification = > {
vec! [ " pass " , " needs-review " , " needs-evidence " , " fail " ]
}
EpiphanyRoleResultRoleId ::Implementation | EpiphanyRoleResultRoleId ::Reorientation = > {
vec! [ ]
}
} ;
let mut properties = serde_json ::json! ( {
" roleId " : {
" type " : " string " ,
" enum " : [ epiphany_role_label ( role_id ) ]
} ,
" verdict " : {
" type " : " string " ,
" enum " : verdict_enum
} ,
" summary " : { " type " : " string " } ,
" nextSafeMove " : { " type " : " string " } ,
" checkpointSummary " : { " type " : " string " } ,
" scratchSummary " : { " type " : " string " } ,
" filesInspected " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" frontierNodeIds " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" evidenceIds " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" openQuestions " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" evidenceGaps " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" risks " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" selfPatch " : {
" type " : " object " ,
2026-06-15 16:38:09 +01:00
" description " : " Optional bounded request to update this role's persistent organ memory. Work organs may update lane habits, durable lessons, goals, values, or private notes; Persona affect/social state belongs only to Persona public surfaces. It must not contain project truth, code edits, job authority, graph/frontier/checkpoint/planning changes, or objective changes. " ,
2026-05-28 21:02:26 +01:00
" required " : [ " agentId " , " reason " ] ,
" properties " : {
" agentId " : {
" type " : " string " ,
2026-06-15 16:38:09 +01:00
" description " : " Expected target persistent agent id for this lane, such as epiphany.modeling or epiphany.soul. "
2026-05-28 21:02:26 +01:00
} ,
" reason " : {
" type " : " string " ,
" description " : " Why this memory mutation makes the lane sharper for future work. "
} ,
" evidenceIds " : {
" type " : " array " ,
" description " : " Optional accepted/project evidence ids that ground the memory request. These do not count as a memory mutation by themselves. " ,
" items " : { " type " : " string " }
} ,
" semanticMemories " : {
" type " : " array " ,
2026-08-07 05:21:32 +01:00
" maxItems " : 8 ,
" items " : self_patch_memory_output_schema ( )
2026-05-28 21:02:26 +01:00
} ,
" episodicMemories " : {
" type " : " array " ,
2026-08-07 05:21:32 +01:00
" maxItems " : 8 ,
" items " : self_patch_memory_output_schema ( )
2026-05-28 21:02:26 +01:00
} ,
" relationshipMemories " : {
" type " : " array " ,
2026-08-07 05:21:32 +01:00
" maxItems " : 8 ,
" items " : self_patch_memory_output_schema ( )
2026-05-28 21:02:26 +01:00
} ,
" goals " : {
" type " : " array " ,
2026-08-07 05:21:32 +01:00
" maxItems " : 6 ,
" items " : self_patch_goal_output_schema ( )
2026-05-28 21:02:26 +01:00
} ,
" values " : {
" type " : " array " ,
2026-08-07 05:21:32 +01:00
" maxItems " : 6 ,
" items " : self_patch_value_output_schema ( )
2026-05-28 21:02:26 +01:00
} ,
" privateNotes " : {
" type " : " array " ,
2026-08-07 05:21:32 +01:00
" maxItems " : 6 ,
" items " : { " type " : " string " , " minLength " : 1 , " maxLength " : 600 }
2026-05-28 21:02:26 +01:00
}
} ,
" additionalProperties " : false
}
} ) ;
let mut required = vec! [
" roleId " ,
" verdict " ,
" summary " ,
" nextSafeMove " ,
" filesInspected " ,
] ;
if role_id = = EpiphanyRoleResultRoleId ::Imagination {
if let Some ( map ) = properties . as_object_mut ( ) {
map . insert (
" statePatch " . to_string ( ) ,
serde_json ::json! ( {
" type " : " object " ,
2026-07-12 00:41:05 +01:00
" description " : " Required reviewable statePatch for Mind admission from Imagination. Use only planning plus optional observations/evidence. planning is a full replacement object and must include at least one objective_drafts entry with status draft. " ,
2026-05-28 21:02:26 +01:00
" required " : [ " planning " ] ,
" properties " : {
" planning " : {
" type " : " object " ,
" required " : [ " objective_drafts " ] ,
" properties " : {
" objective_drafts " : {
" type " : " array " ,
" minItems " : 1 ,
2026-08-13 22:14:56 +02:00
" items " : objective_draft_output_schema ( )
2026-05-28 21:02:26 +01:00
}
} ,
2026-08-13 22:14:56 +02:00
" additionalProperties " : false
2026-05-28 21:02:26 +01:00
}
} ,
2026-08-13 22:14:56 +02:00
" additionalProperties " : false
2026-05-28 21:02:26 +01:00
} ) ,
) ;
}
required . push ( " statePatch " ) ;
2026-05-30 01:02:16 +01:00
} else if role_id = = EpiphanyRoleResultRoleId ::Research {
if let Some ( map ) = properties . as_object_mut ( ) {
map . insert (
" statePatch " . to_string ( ) ,
serde_json ::json! ( {
" type " : " object " ,
2026-08-18 00:34:51 +02:00
" description " : " Required reviewable statePatch for Mind admission from Research/Eyes. Use only keyed observations, keyed evidence, and an optional investigationCheckpoint. Scratch is pass-local and is not durable Mind state. The patch must include at least one evidence record and one observation that cites it. " ,
2026-05-30 01:02:16 +01:00
" required " : [ " observations " , " evidence " ] ,
" properties " : {
" observations " : {
" type " : " array " ,
" minItems " : 1 ,
2026-08-13 22:14:56 +02:00
" items " : observation_output_schema ( )
2026-05-30 01:02:16 +01:00
} ,
" evidence " : {
" type " : " array " ,
" minItems " : 1 ,
2026-08-13 22:14:56 +02:00
" items " : evidence_output_schema ( )
2026-07-16 16:49:45 +01:00
} ,
2026-08-13 22:14:56 +02:00
" investigationCheckpoint " : investigation_checkpoint_output_schema ( )
2026-05-30 01:02:16 +01:00
} ,
2026-08-13 22:14:56 +02:00
" additionalProperties " : false
2026-05-30 01:02:16 +01:00
} ) ,
) ;
}
required . push ( " statePatch " ) ;
2026-05-28 21:02:26 +01:00
} else if role_id = = EpiphanyRoleResultRoleId ::Modeling {
if let Some ( map ) = properties . as_object_mut ( ) {
2026-07-15 22:06:06 +01:00
map . insert (
2026-08-14 16:19:35 +02:00
" repoModelOperations " . to_string ( ) ,
2026-07-15 00:43:05 +01:00
serde_json ::json! ( {
2026-08-14 16:19:35 +02:00
" type " : " array " ,
" description " : " Semantic keyed RepoModel operations only. The runtime owns proposal identity, the exact Body and RepoModel basis, causal request/result/evidence bindings, strong reads, writes, timestamps, and receipts. " ,
" items " : {
" anyOf " : [
{ " type " : " object " , " required " : [ " operation " , " node " ] , " properties " : { " operation " : { " const " : " put_node " } , " node " : repo_model_node_output_schema ( ) } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " node_id " ] , " properties " : { " operation " : { " const " : " retire_node " } , " node_id " : { " type " : " string " , " minLength " : 1 } } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " edge " ] , " properties " : { " operation " : { " const " : " put_edge " } , " edge " : repo_model_edge_output_schema ( ) } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " edge_id " ] , " properties " : { " operation " : { " const " : " retire_edge " } , " edge_id " : { " type " : " string " , " minLength " : 1 } } , " additionalProperties " : false } ,
2026-08-14 17:24:25 +02:00
{ " type " : " object " , " required " : [ " operation " , " item " ] , " properties " : { " operation " : { " const " : " put_frontier " } , " item " : repo_frontier_item_output_schema ( ) } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " label " , " contract " , " source_refs " ] , " properties " : { " operation " : { " const " : " create_surface_offer " } , " label " : { " type " : " string " , " minLength " : 1 } , " contract " : atlas_contract_descriptor_output_schema ( ) , " source_refs " : { " type " : " array " , " minItems " : 1 , " uniqueItems " : true , " items " : { " type " : " string " , " minLength " : 1 } } } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " surface_id " ] , " properties " : { " operation " : { " const " : " deprecate_surface_offer " } , " surface_id " : { " type " : " string " , " format " : " uuid " } , " replacement_surface_id " : { " type " : " string " , " format " : " uuid " } } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " surface_id " ] , " properties " : { " operation " : { " const " : " withdraw_surface_offer " } , " surface_id " : { " type " : " string " , " format " : " uuid " } } , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " label " , " target " , " entanglement_kind " , " failure_semantics " , " impact_scope " , " source_refs " ] , " properties " : {
" operation " : { " const " : " create_dependency_claim " } ,
" label " : { " type " : " string " , " minLength " : 1 } ,
" target " : atlas_dependency_target_output_schema ( ) ,
" entanglement_kind " : { " type " : " string " , " enum " : [ " build " , " runtime " , " deployment " , " schema_protocol " , " data_state " , " infrastructure_control " , " governance " , " lore_persona " ] } ,
" failure_semantics " : { " type " : " string " , " enum " : [ " fail_closed " , " degrade " , " last_known_safe " , " human_decision " ] } ,
" impact_scope " : atlas_impact_scope_output_schema ( ) ,
" source_refs " : { " type " : " array " , " minItems " : 1 , " uniqueItems " : true , " items " : { " type " : " string " , " minLength " : 1 } }
} , " additionalProperties " : false } ,
{ " type " : " object " , " required " : [ " operation " , " claim_id " ] , " properties " : { " operation " : { " const " : " retire_dependency_claim " } , " claim_id " : { " type " : " string " , " format " : " uuid " } } , " additionalProperties " : false }
2026-08-14 16:19:35 +02:00
]
}
2026-07-15 00:43:05 +01:00
} ) ,
) ;
2026-07-13 22:29:10 +01:00
map . insert (
" statePatch " . to_string ( ) ,
serde_json ::json! ( {
" type " : " object " ,
2026-08-14 16:19:35 +02:00
" description " : " Optional generic Mind-reviewable observations/evidence only. Repository anatomy belongs exclusively in repoModelOperations. " ,
2026-07-13 22:29:10 +01:00
" properties " : {
2026-07-16 16:49:45 +01:00
" observations " : { " type " : " array " , " items " : observation_output_schema ( ) } ,
" evidence " : { " type " : " array " , " items " : evidence_output_schema ( ) }
2026-07-13 22:29:10 +01:00
} ,
" additionalProperties " : false
} ) ,
) ;
2026-05-28 21:02:26 +01:00
}
required . push ( " frontierNodeIds " ) ;
2026-08-14 16:19:35 +02:00
required . push ( " repoModelOperations " ) ;
2026-05-28 21:02:26 +01:00
}
2026-07-13 22:29:10 +01:00
let mut schema = serde_json ::json! ( {
2026-05-28 21:02:26 +01:00
" type " : " object " ,
" properties " : properties ,
" required " : required ,
" additionalProperties " : true
2026-07-13 22:29:10 +01:00
} ) ;
if role_id = = EpiphanyRoleResultRoleId ::Modeling {
2026-07-15 00:43:05 +01:00
schema [ " allOf " ] = serde_json ::json! ( [
{
" if " : {
2026-08-14 16:19:35 +02:00
" properties " : { " verdict " : { " const " : " checkpoint-update-needed " } } ,
" required " : [ " verdict " ]
2026-07-15 00:43:05 +01:00
} ,
2026-08-07 01:35:51 +01:00
" then " : {
" properties " : {
2026-08-14 16:19:35 +02:00
" repoModelOperations " : {
" minItems " : 1 ,
" contains " : {
" type " : " object " ,
" properties " : { " operation " : { " const " : " put_frontier " } } ,
" required " : [ " operation " ]
2026-08-08 15:57:14 +01:00
} ,
2026-08-14 16:19:35 +02:00
" minContains " : 1 ,
" maxContains " : 1
2026-08-08 15:57:14 +01:00
}
2026-08-14 16:19:35 +02:00
}
2026-08-08 15:57:14 +01:00
}
} ,
{
" if " : {
2026-08-14 17:24:25 +02:00
" properties " : { " verdict " : { " const " : " regather-needed " } } ,
2026-08-14 16:19:35 +02:00
" required " : [ " verdict " ]
2026-08-08 03:35:02 +01:00
} ,
" then " : {
2026-08-14 16:19:35 +02:00
" properties " : { " repoModelOperations " : { " maxItems " : 0 } }
2026-08-08 03:35:02 +01:00
}
2026-07-15 00:43:05 +01:00
}
] ) ;
2026-07-13 22:29:10 +01:00
}
schema
2026-05-28 21:02:26 +01:00
}
2026-08-11 08:51:58 +02:00
pub fn epiphany_proposal_modeling_output_schema (
source_kind : crate ::RepoFrontierProposalSourceKind ,
) -> serde_json ::Value {
let recommended_organs = match source_kind {
crate ::RepoFrontierProposalSourceKind ::Imagination = > vec! [ " Eyes " , " Imagination " ] ,
crate ::RepoFrontierProposalSourceKind ::User
| crate ::RepoFrontierProposalSourceKind ::Persona
| crate ::RepoFrontierProposalSourceKind ::Bifrost = > {
vec! [ " Hands " , " Eyes " , " Imagination " ]
}
} ;
serde_json ::json! ( {
" type " : " object " ,
" required " : [
" roleId " , " verdict " , " summary " , " nextSafeMove " , " filesInspected " ,
" frontierNodeIds " , " evidenceIds " , " proposalFrontierDraft "
] ,
" properties " : {
2026-08-11 09:16:36 +02:00
" roleId " : { " type " : " string " , " const " : " modeling " } ,
2026-08-11 08:51:58 +02:00
" verdict " : {
" type " : " string " ,
" enum " : [ " checkpoint-ready " , " checkpoint-update-needed " , " regather-needed " ]
} ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" nextSafeMove " : { " type " : " string " , " minLength " : 1 } ,
" filesInspected " : { " type " : " array " , " items " : { " type " : " string " } } ,
" frontierNodeIds " : { " type " : " array " , " items " : { " type " : " string " } } ,
" evidenceIds " : { " type " : " array " , " items " : { " type " : " string " } } ,
" proposalFrontierDraft " : {
" type " : " object " ,
" required " : [
" migrationBody " , " question " , " gap " , " targetClaimIds " , " sourceScope " ,
" recommendedNextOrgan " , " dependencyItemIds " , " evidenceRefs "
] ,
" properties " : {
" migrationBody " : { " type " : " string " , " minLength " : 1 } ,
" question " : { " type " : " string " , " minLength " : 1 } ,
" gap " : { " type " : " string " , " minLength " : 1 } ,
" targetClaimIds " : { " type " : " array " , " items " : { " type " : " string " } } ,
" sourceScope " : {
" type " : " array " ,
" minItems " : 1 ,
" items " : { " type " : " string " , " minLength " : 1 }
} ,
" recommendedNextOrgan " : { " type " : " string " , " enum " : recommended_organs } ,
" dependencyItemIds " : { " type " : " array " , " items " : { " type " : " string " } } ,
" evidenceRefs " : { " type " : " array " , " items " : { " type " : " string " } }
} ,
" additionalProperties " : false
}
} ,
" additionalProperties " : false
} )
}
2026-08-08 14:56:29 +01:00
pub fn epiphany_frontier_verdict_modeling_output_schema (
authority : & crate ::RepoFrontierVerdictModelingLaunchAuthority ,
) -> serde_json ::Value {
2026-08-14 16:19:35 +02:00
let _authority = authority ;
2026-08-08 14:10:29 +01:00
let mut schema = epiphany_role_launch_output_schema ( EpiphanyRoleResultRoleId ::Modeling ) ;
2026-08-14 16:19:35 +02:00
schema [ " properties " ]
. as_object_mut ( )
. expect ( " role schema properties must be an object " )
. remove ( " repoModelOperations " ) ;
schema [ " properties " ] [ " frontierVerdictGap " ] = serde_json ::json! ( {
2026-08-08 14:10:29 +01:00
" type " : " string " ,
2026-08-14 16:19:35 +02:00
" minLength " : 1 ,
" description " : " Semantic explanation of the allowed resolved/blocked transition. Runtime owns the exact frontier, disposition, evidence bindings, timestamps, proposal, reads, writes, and receipts. "
2026-08-08 14:10:29 +01:00
} ) ;
schema [ " properties " ] [ " evidenceIds " ] [ " minItems " ] = serde_json ::json! ( 1 ) ;
2026-08-14 16:19:35 +02:00
let required = schema [ " required " ]
2026-08-08 14:10:29 +01:00
. as_array_mut ( )
2026-08-14 16:19:35 +02:00
. expect ( " role schema required must be an array " ) ;
required . retain ( | field | field . as_str ( ) ! = Some ( " repoModelOperations " ) ) ;
required . push ( serde_json ::json! ( " frontierVerdictGap " ) ) ;
2026-08-08 14:10:29 +01:00
schema [ " allOf " ] = serde_json ::json! ( [ ] ) ;
schema
}
2026-07-15 01:29:35 +01:00
pub fn epiphany_frontier_planning_output_schema ( ) -> serde_json ::Value {
let mut schema = epiphany_role_launch_output_schema ( EpiphanyRoleResultRoleId ::Imagination ) ;
let properties = schema [ " properties " ]
. as_object_mut ( )
. expect ( " role output schema properties " ) ;
properties . remove ( " statePatch " ) ;
properties . remove ( " selfPatch " ) ;
properties . insert (
" frontierPlanCandidate " . to_string ( ) ,
serde_json ::json! ( {
" type " : " object " ,
" required " : [
2026-08-14 16:19:35 +02:00
" safe_paths " , " action " , " command " , " checks " , " stop_conditions " ,
" rollback_steps " , " commit_message "
2026-07-15 01:29:35 +01:00
] ,
" properties " : {
2026-08-08 10:30:47 +01:00
" safe_paths " : {
" type " : " array " ,
" minItems " : 1 ,
" description " : " A strict lexicographically sorted, duplicate-free narrowing of the immutable planning context source_scope. Every path must equal one source_scope entry or be a descendant of one; never add an adjacent or otherwise unscoped path. " ,
" items " : { " type " : " string " , " minLength " : 1 }
} ,
2026-07-15 01:29:35 +01:00
" action " : { " type " : " string " , " minLength " : 1 } ,
" command " : { " type " : " string " , " minLength " : 1 } ,
" checks " : { " type " : " array " , " minItems " : 1 , " items " : { " type " : " string " , " minLength " : 1 } } ,
" stop_conditions " : { " type " : " array " , " minItems " : 1 , " items " : { " type " : " string " , " minLength " : 1 } } ,
" rollback_steps " : { " type " : " array " , " minItems " : 1 , " items " : { " type " : " string " , " minLength " : 1 } } ,
2026-08-14 16:19:35 +02:00
" commit_message " : { " type " : " string " , " minLength " : 1 }
2026-07-15 01:29:35 +01:00
} ,
" additionalProperties " : false
} ) ,
) ;
schema [ " required " ] = serde_json ::json! ( [
" roleId " ,
" verdict " ,
" summary " ,
" nextSafeMove " ,
" filesInspected " ,
" frontierPlanCandidate "
] ) ;
schema [ " additionalProperties " ] = serde_json ::Value ::Bool ( false ) ;
schema
}
2026-07-15 03:05:11 +01:00
pub fn epiphany_frontier_plan_mind_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" properties " : {
" roleId " : { " type " : " string " , " const " : " mindAdmissionReview " } ,
" verdict " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" nextSafeMove " : { " type " : " string " , " minLength " : 1 } ,
" filesInspected " : { " type " : " array " , " items " : { " type " : " string " } } ,
" frontierPlanMindDecision " : {
" type " : " object " ,
2026-08-14 16:19:35 +02:00
" description " : " Semantic Mind disposition only. Runtime binds the exact request, planning candidate, keyed RepoModel basis, source versions, receipt identity, and decision time. " ,
" required " : [ " decision " , " rationale " ] ,
2026-07-15 03:05:11 +01:00
" properties " : {
2026-08-14 16:19:35 +02:00
" decision " : { " type " : " string " , " enum " : [ " adopt " , " refuse " , " hold " ] } ,
" rationale " : { " type " : " string " , " minLength " : 1 }
2026-07-15 03:05:11 +01:00
} , " additionalProperties " : false
}
} ,
2026-08-14 16:19:35 +02:00
" required " : [ " roleId " , " verdict " , " summary " , " nextSafeMove " , " filesInspected " , " frontierPlanMindDecision " ] ,
2026-07-15 03:05:11 +01:00
" additionalProperties " : false
} )
}
2026-07-18 20:31:57 +01:00
pub fn epiphany_imagination_consideration_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" properties " : {
" roleId " : { " type " : " string " , " const " : " imagination " } ,
" verdict " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" nextSafeMove " : { " type " : " string " , " minLength " : 1 } ,
" filesInspected " : { " type " : " array " , " items " : { " type " : " string " } } ,
" imaginationConsiderationCandidate " : {
" type " : " object " ,
2026-08-11 05:22:53 +02:00
" required " : [ " disposition " , " title " , " summary " , " rationale " , " option_drafts " , " uncertainties " ,
2026-08-11 05:41:35 +02:00
" recommended_review_route " ] ,
2026-07-18 20:31:57 +01:00
" properties " : {
" disposition " : { " type " : " string " , " enum " : [ " suggest " , " hold " , " no_fit " ] } ,
" title " : { " type " : " string " , " minLength " : 1 } , " summary " : { " type " : " string " , " minLength " : 1 } ,
" rationale " : { " type " : " string " , " minLength " : 1 } ,
" option_drafts " : { " type " : " array " , " items " : { " type " : " object " , " required " : [ " title " , " summary " ] ,
" properties " : { " title " : { " type " : " string " , " minLength " : 1 } , " summary " : { " type " : " string " , " minLength " : 1 } } ,
" additionalProperties " : false } } ,
" uncertainties " : { " type " : " array " , " items " : { " type " : " string " } } ,
2026-08-11 05:22:53 +02:00
" recommended_review_route " : { " type " : " string " , " enum " : [ " modeling_review " , " hold " , " silence " ] }
2026-07-18 20:31:57 +01:00
} ,
" additionalProperties " : false
}
} ,
" required " : [ " roleId " , " verdict " , " summary " , " nextSafeMove " , " filesInspected " ,
2026-08-11 05:22:53 +02:00
" imaginationConsiderationCandidate " ] ,
2026-07-18 20:31:57 +01:00
" additionalProperties " : false
} )
}
2026-07-19 00:03:11 +01:00
pub fn epiphany_admitted_model_direction_consideration_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" properties " : {
" roleId " : { " type " : " string " , " const " : " imagination " } ,
" verdict " : { " type " : " string " , " minLength " : 1 } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
" nextSafeMove " : { " type " : " string " , " minLength " : 1 } ,
" filesInspected " : { " type " : " array " , " items " : { " type " : " string " } } ,
" admittedModelDirectionConsiderationResult " : {
" type " : " object " ,
2026-08-11 05:22:53 +02:00
" required " : [ " disposition " , " summary " , " option_drafts " , " uncertainties " , " evidence_refs " ] ,
2026-07-19 00:03:11 +01:00
" properties " : {
" disposition " : { " type " : " string " , " enum " : [ " suggest " , " hold " , " no_fit " ] } ,
" summary " : { " type " : " string " , " minLength " : 1 } ,
2026-08-11 14:42:40 +02:00
" option_drafts " : { " type " : " array " , " maxItems " : crate ::admitted_model_direction_consideration ::MAX_OPTION_DRAFTS , " items " : { " type " : " object " , " required " : [ " title " , " summary " ] ,
2026-07-19 00:03:11 +01:00
" properties " : { " title " : { " type " : " string " , " minLength " : 1 } , " summary " : { " type " : " string " , " minLength " : 1 } } ,
" additionalProperties " : false } } ,
" uncertainties " : { " type " : " array " , " items " : { " type " : " string " } } ,
2026-08-11 05:22:53 +02:00
" evidence_refs " : { " type " : " array " , " items " : { " type " : " string " } }
2026-07-19 00:03:11 +01:00
} ,
" additionalProperties " : false
}
} ,
" required " : [ " roleId " , " verdict " , " summary " , " nextSafeMove " , " filesInspected " ,
2026-08-11 05:22:53 +02:00
" admittedModelDirectionConsiderationResult " ] ,
2026-07-19 00:03:11 +01:00
" additionalProperties " : false
} )
}
2026-05-28 21:02:26 +01:00
pub fn epiphany_reorient_launch_output_schema ( ) -> serde_json ::Value {
serde_json ::json! ( {
" type " : " object " ,
" properties " : {
" mode " : {
" type " : " string " ,
" enum " : [ " resume " , " regather " ]
} ,
" summary " : { " type " : " string " } ,
" nextSafeMove " : { " type " : " string " } ,
" checkpointStillValid " : { " type " : " boolean " } ,
" filesInspected " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" frontierNodeIds " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" evidenceIds " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" openQuestions " : {
" type " : " array " ,
" items " : { " type " : " string " }
} ,
" continuityRisks " : {
" type " : " array " ,
" items " : { " type " : " string " }
}
} ,
" required " : [ " mode " , " summary " , " nextSafeMove " ] ,
" additionalProperties " : true
} )
}
const EPIPHANY_SPECIALIST_PROMPTS_TOML : & str = include_str! ( " prompts/epiphany_specialists.toml " ) ;
const EPIPHANY_WORKER_BOUNDARY_PROMPT : & str = r #" ## Epiphany Worker Boundary
You are one bounded Epiphany worker for this launch only . Your authority comes from the typed launch document , the role - local instruction , and the declared output contract .
Do the role , name uncertainty , and return the required JSON object . Do not become the coordinator , do not accept or promote your own output , do not invent durable state outside an allowed statePatch , and do not treat model transport or Codex machinery as prompt authority .
2026-07-13 22:29:10 +01:00
If you learned a durable role - local habit , you may include a bounded selfPatch . Project truth belongs in the role ' s typed output artifact or evidence , not memory . " #;
2026-05-28 21:02:26 +01:00
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanySpecialistPromptConfig {
pub shared : EpiphanySharedPromptConfig ,
pub roles : EpiphanyRolePromptConfig ,
// Parsed here so the bundled prompt config fails fast even though the GUI runner consumes it.
#[ allow(dead_code) ]
pub implementation : EpiphanyImplementationPromptConfig ,
pub reorientation : EpiphanyReorientationPromptConfig ,
pub coordinator : EpiphanyCoordinatorPromptConfig ,
pub crrc : EpiphanyCrrcPromptConfig ,
}
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanySharedPromptConfig {
pub persistent_memory : String ,
}
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanyRolePromptConfig {
pub imagination : String ,
2026-07-15 03:05:11 +01:00
pub mind : String ,
2026-05-28 21:02:26 +01:00
pub modeling : String ,
pub verification : String ,
#[ allow(dead_code) ]
pub research : String ,
#[ allow(dead_code) ]
pub repo_personality : String ,
#[ allow(dead_code) ]
pub repo_memory : String ,
#[ allow(dead_code) ]
2026-06-15 16:38:09 +01:00
pub persona : String ,
2026-05-28 21:02:26 +01:00
}
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanyImplementationPromptConfig {
#[ allow(dead_code) ]
pub continue_template : String ,
}
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanyReorientationPromptConfig {
pub resume : String ,
pub regather : String ,
}
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanyCoordinatorPromptConfig {
pub note_template : String ,
}
#[ derive(Debug, serde::Deserialize) ]
pub struct EpiphanyCrrcPromptConfig {
pub pre_compaction_checkpoint_intervention : String ,
}
pub fn epiphany_specialist_prompt_config ( ) -> & 'static EpiphanySpecialistPromptConfig {
static CONFIG : OnceLock < EpiphanySpecialistPromptConfig > = OnceLock ::new ( ) ;
CONFIG . get_or_init ( | | {
toml ::from_str ( EPIPHANY_SPECIALIST_PROMPTS_TOML )
. expect ( " bundled Epiphany specialist prompt config must parse " )
} )
}
pub fn epiphany_agent_prompt_with_memory ( body : & str ) -> String {
let memory = epiphany_specialist_prompt_config ( )
. shared
. persistent_memory
. trim ( ) ;
let body = body . trim ( ) ;
if memory . is_empty ( ) {
body . to_string ( )
} else if body . is_empty ( ) {
memory . to_string ( )
} else {
format! ( " {memory} \n \n {body} " )
}
}
pub fn epiphany_worker_prompt ( body : & str ) -> String {
let body = body . trim ( ) ;
if body . is_empty ( ) {
EPIPHANY_WORKER_BOUNDARY_PROMPT . to_string ( )
} else {
format! ( " {} \n \n {} " , EPIPHANY_WORKER_BOUNDARY_PROMPT , body )
}
}
pub fn build_epiphany_role_launch_request (
thread_id : & str ,
role_id : EpiphanyRoleResultRoleId ,
expected_revision : Option < u64 > ,
max_runtime_seconds : Option < u64 > ,
state : & EpiphanyThreadState ,
2026-06-02 13:57:47 +01:00
) -> Result < EpiphanyJobLaunchRequest , String > {
build_epiphany_role_launch_request_with_dynamic_context (
thread_id ,
role_id ,
expected_revision ,
max_runtime_seconds ,
state ,
None ,
)
}
pub fn build_epiphany_role_launch_request_with_dynamic_context (
thread_id : & str ,
role_id : EpiphanyRoleResultRoleId ,
expected_revision : Option < u64 > ,
max_runtime_seconds : Option < u64 > ,
state : & EpiphanyThreadState ,
dynamic_prompt_context : Option < String > ,
2026-05-28 21:02:26 +01:00
) -> Result < EpiphanyJobLaunchRequest , String > {
let binding_id = epiphany_role_binding_id ( role_id ) ? ;
let owner_role = epiphany_role_owner ( role_id ) ? ;
let linked_subgoal_ids = epiphany_active_subgoal_ids ( Some ( state ) ) ;
let linked_graph_node_ids = epiphany_active_graph_node_ids ( Some ( state ) ) ;
let ( scope , authority_scope , instruction ) = match role_id {
EpiphanyRoleResultRoleId ::Imagination = > (
" role-scoped planning synthesis " ,
" epiphany.role.imagination " ,
build_epiphany_role_launch_instruction ( role_id ) ,
) ,
2026-05-30 01:02:16 +01:00
EpiphanyRoleResultRoleId ::Research = > (
" role-scoped source gathering " ,
" epiphany.role.research " ,
build_epiphany_role_launch_instruction ( role_id ) ,
) ,
2026-05-28 21:02:26 +01:00
EpiphanyRoleResultRoleId ::Modeling = > (
" role-scoped modeling/checkpoint maintenance " ,
" epiphany.role.modeling " ,
build_epiphany_role_launch_instruction ( role_id ) ,
) ,
EpiphanyRoleResultRoleId ::Verification = > (
" role-scoped verification/review " ,
" epiphany.role.verification " ,
build_epiphany_role_launch_instruction ( role_id ) ,
) ,
EpiphanyRoleResultRoleId ::Implementation | EpiphanyRoleResultRoleId ::Reorientation = > {
return Err ( epiphany_role_binding_id ( role_id ) . unwrap_err ( ) ) ;
}
} ;
let launch_document = EpiphanyWorkerLaunchDocument ::Role ( EpiphanyRoleWorkerLaunchDocument {
thread_id : thread_id . to_string ( ) ,
role_id : epiphany_role_label ( role_id ) . to_string ( ) ,
state_revision : state . revision ,
objective : state . objective . clone ( ) ,
2026-06-02 13:57:47 +01:00
dynamic_prompt_context ,
2026-07-15 22:06:06 +01:00
repository_body_observation_basis : None ,
2026-07-14 01:03:54 +01:00
proposal_modeling_context : None ,
2026-08-17 23:27:48 +02:00
frontier_verdict_modeling_context : None ,
2026-07-15 01:03:59 +01:00
frontier_planning_context : None ,
2026-08-11 23:11:08 +02:00
frontier_research_context : None ,
2026-08-18 01:34:31 +02:00
frontier_verification_context : None ,
2026-07-15 03:05:11 +01:00
frontier_plan_mind_context : None ,
2026-07-18 20:31:57 +01:00
imagination_consideration_context : None ,
2026-07-19 00:03:11 +01:00
admitted_model_direction_consideration_context : None ,
2026-05-28 21:02:26 +01:00
active_subgoal_id : state . active_subgoal_id . clone ( ) ,
active_subgoals : state
. subgoals
. iter ( )
. filter ( | subgoal | Some ( subgoal . id . as_str ( ) ) = = state . active_subgoal_id . as_deref ( ) )
. cloned ( )
. collect ( ) ,
active_graph_node_ids : linked_graph_node_ids . clone ( ) ,
investigation_checkpoint : state . investigation_checkpoint . clone ( ) ,
scratch : state . scratch . clone ( ) ,
invariants : state . invariants . clone ( ) ,
graphs : Some ( state . graphs . clone ( ) ) ,
recent_evidence : state . recent_evidence . iter ( ) . take ( 8 ) . cloned ( ) . collect ( ) ,
recent_observations : state . observations . iter ( ) . take ( 8 ) . cloned ( ) . collect ( ) ,
graph_frontier : state . graph_frontier . clone ( ) ,
graph_checkpoint : state . graph_checkpoint . clone ( ) ,
planning : Some ( state . planning . clone ( ) ) ,
churn : state . churn . clone ( ) ,
} ) ;
let output_contract_id = launch_document . output_contract_id ( ) . to_string ( ) ;
let organ_launch_contract = default_launch_organ_contract (
authority_scope ,
launch_document . document_kind ( ) ,
& output_contract_id ,
) ;
Ok ( EpiphanyJobLaunchRequest {
expected_revision ,
binding_id : binding_id . to_string ( ) ,
kind : CoreEpiphanyJobKind ::Specialist ,
scope : scope . to_string ( ) ,
owner_role : owner_role . to_string ( ) ,
authority_scope : authority_scope . to_string ( ) ,
linked_subgoal_ids ,
linked_graph_node_ids : epiphany_active_graph_node_ids ( Some ( state ) ) ,
instruction ,
launch_document ,
output_contract_id ,
organ_launch_contract ,
max_runtime_seconds ,
2026-07-14 01:03:54 +01:00
proposal_modeling_request_id : None ,
2026-07-15 01:03:59 +01:00
frontier_planning_request_id : None ,
2026-07-15 03:05:11 +01:00
frontier_plan_mind_request_id : None ,
2026-07-18 20:31:57 +01:00
imagination_consideration_request_id : None ,
2026-07-19 00:03:11 +01:00
admitted_model_direction_consideration_request_id : None ,
2026-08-08 14:10:29 +01:00
repo_frontier_modeling_request_id : None ,
2026-08-11 23:11:08 +02:00
repo_frontier_research_request_id : None ,
2026-08-18 01:34:31 +02:00
repo_frontier_verification_request_id : None ,
2026-05-28 21:02:26 +01:00
} )
}
2026-07-18 20:31:57 +01:00
pub fn build_epiphany_imagination_consideration_launch_request (
thread_id : & str ,
expected_revision : Option < u64 > ,
max_runtime_seconds : Option < u64 > ,
state : & EpiphanyThreadState ,
request_id : String ,
) -> Result < EpiphanyJobLaunchRequest , String > {
let mut launch = build_epiphany_role_launch_request_with_dynamic_context (
thread_id ,
EpiphanyRoleResultRoleId ::Imagination ,
expected_revision ,
max_runtime_seconds ,
state ,
None ,
) ? ;
launch . scope = " role-scoped organizational feedback consideration " . into ( ) ;
launch . authority_scope = " epiphany.imagination.consideration.proposal_only " . into ( ) ;
launch . instruction = " Await coordinator-owned typed consideration context. " . into ( ) ;
launch . organ_launch_contract = default_launch_organ_contract (
& launch . authority_scope ,
launch . launch_document . document_kind ( ) ,
& launch . output_contract_id ,
) ;
launch . imagination_consideration_request_id = Some ( request_id ) ;
Ok ( launch )
}
2026-07-19 00:03:11 +01:00
pub fn build_epiphany_admitted_model_direction_consideration_launch_request (
thread_id : & str ,
expected_revision : Option < u64 > ,
max_runtime_seconds : Option < u64 > ,
state : & EpiphanyThreadState ,
request_id : String ,
) -> Result < EpiphanyJobLaunchRequest , String > {
let mut launch = build_epiphany_role_launch_request_with_dynamic_context (
thread_id ,
EpiphanyRoleResultRoleId ::Imagination ,
expected_revision ,
max_runtime_seconds ,
state ,
None ,
) ? ;
launch . scope = " role-scoped admitted Modeling-map direction consideration " . into ( ) ;
launch . authority_scope =
" epiphany.imagination.admitted_model_direction_consideration.proposal_only " . into ( ) ;
launch . instruction = " Await coordinator-owned typed admitted model context. " . into ( ) ;
launch . organ_launch_contract = default_launch_organ_contract (
& launch . authority_scope ,
launch . launch_document . document_kind ( ) ,
& launch . output_contract_id ,
) ;
launch . admitted_model_direction_consideration_request_id = Some ( request_id ) ;
Ok ( launch )
}
2026-05-28 21:02:26 +01:00
fn build_epiphany_role_launch_instruction ( role_id : EpiphanyRoleResultRoleId ) -> String {
let prompts = & epiphany_specialist_prompt_config ( ) . roles ;
let body = match role_id {
EpiphanyRoleResultRoleId ::Imagination = > prompts . imagination . as_str ( ) ,
2026-05-30 01:02:16 +01:00
EpiphanyRoleResultRoleId ::Research = > prompts . research . as_str ( ) ,
2026-05-28 21:02:26 +01:00
EpiphanyRoleResultRoleId ::Modeling = > prompts . modeling . as_str ( ) ,
EpiphanyRoleResultRoleId ::Verification = > prompts . verification . as_str ( ) ,
EpiphanyRoleResultRoleId ::Implementation | EpiphanyRoleResultRoleId ::Reorientation = > {
" Unsupported Epiphany role specialist template. "
}
} ;
epiphany_worker_prompt ( body )
}
pub fn build_epiphany_reorient_launch_instruction ( action : CoreEpiphanyReorientAction ) -> String {
let prompts = & epiphany_specialist_prompt_config ( ) . reorientation ;
let body = match action {
CoreEpiphanyReorientAction ::Resume = > prompts . resume . as_str ( ) ,
CoreEpiphanyReorientAction ::Regather = > prompts . regather . as_str ( ) ,
} ;
epiphany_worker_prompt ( body )
}
pub fn build_epiphany_job_launch_request (
expected_revision : Option < u64 > ,
binding_id : String ,
kind : CoreEpiphanyJobKind ,
scope : String ,
owner_role : String ,
authority_scope : String ,
linked_subgoal_ids : Vec < String > ,
linked_graph_node_ids : Vec < String > ,
instruction : String ,
launch_document : EpiphanyWorkerLaunchDocument ,
output_contract_id : String ,
max_runtime_seconds : Option < u64 > ,
) -> EpiphanyJobLaunchRequest {
let organ_launch_contract = default_launch_organ_contract (
& authority_scope ,
launch_document . document_kind ( ) ,
& output_contract_id ,
) ;
EpiphanyJobLaunchRequest {
expected_revision ,
binding_id ,
kind ,
scope ,
owner_role ,
authority_scope ,
linked_subgoal_ids ,
linked_graph_node_ids ,
instruction ,
launch_document ,
output_contract_id ,
organ_launch_contract ,
max_runtime_seconds ,
2026-07-14 01:03:54 +01:00
proposal_modeling_request_id : None ,
2026-07-15 01:03:59 +01:00
frontier_planning_request_id : None ,
2026-07-15 03:05:11 +01:00
frontier_plan_mind_request_id : None ,
2026-07-18 20:31:57 +01:00
imagination_consideration_request_id : None ,
2026-07-19 00:03:11 +01:00
admitted_model_direction_consideration_request_id : None ,
2026-08-08 14:10:29 +01:00
repo_frontier_modeling_request_id : None ,
2026-08-11 23:11:08 +02:00
repo_frontier_research_request_id : None ,
2026-08-18 01:34:31 +02:00
repo_frontier_verification_request_id : None ,
2026-05-28 21:02:26 +01:00
}
}
pub fn render_epiphany_coordinator_note (
crrc_action : CoreEpiphanyCrrcAction ,
pressure_level : CoreEpiphanyPressureLevel ,
modeling_result_status : CoreEpiphanyCoordinatorRoleResultStatus ,
verification_result_status : CoreEpiphanyCoordinatorRoleResultStatus ,
reorient_result_status : CoreEpiphanyCrrcResultStatus ,
coordinator_action : CoreEpiphanyCoordinatorAction ,
) -> String {
let template = epiphany_agent_prompt_with_memory (
& epiphany_specialist_prompt_config ( )
. coordinator
. note_template ,
) ;
template
. trim ( )
. replace ( " {crrc_action} " , & format! ( " {crrc_action:?} " ) )
. replace ( " {pressure_level} " , & format! ( " {pressure_level:?} " ) )
. replace (
" {modeling_result_status} " ,
& format! ( " {modeling_result_status:?} " ) ,
)
. replace (
" {verification_result_status} " ,
& format! ( " {verification_result_status:?} " ) ,
)
. replace (
" {reorient_result_status} " ,
& format! ( " {reorient_result_status:?} " ) ,
)
. replace ( " {coordinator_action} " , & format! ( " {coordinator_action:?} " ) )
}
pub fn render_epiphany_pre_compaction_checkpoint_intervention (
pressure : & EpiphanyPressure ,
) -> String {
let usage = match (
pressure . used_tokens ,
pressure . remaining_tokens ,
pressure . ratio_per_mille ,
) {
( Some ( used ) , Some ( remaining ) , Some ( ratio ) ) = > format! (
" {used} tokens used, {remaining} remaining, {}.{}% of the selected limit " ,
ratio / 10 ,
ratio % 10
) ,
( Some ( used ) , _ , _ ) = > format! ( " {used} tokens used " ) ,
_ = > " token usage known only as a pressure threshold crossing " . to_string ( ) ,
} ;
let template = epiphany_agent_prompt_with_memory (
& epiphany_specialist_prompt_config ( )
. crrc
. pre_compaction_checkpoint_intervention ,
) ;
template
. trim ( )
. replace (
" {pressure_level} " ,
core_pressure_level_label ( pressure . level ) ,
)
. replace ( " {usage} " , & usage )
}
fn core_pressure_level_label ( level : CoreEpiphanyPressureLevel ) -> & 'static str {
match level {
CoreEpiphanyPressureLevel ::Unknown = > " unknown " ,
CoreEpiphanyPressureLevel ::Low = > " low " ,
CoreEpiphanyPressureLevel ::Elevated = > " elevated " ,
CoreEpiphanyPressureLevel ::High = > " high " ,
CoreEpiphanyPressureLevel ::Critical = > " critical " ,
}
}
pub fn unique_strings ( values : impl IntoIterator < Item = String > ) -> Vec < String > {
let mut unique = Vec ::new ( ) ;
extend_unique_strings ( & mut unique , values ) ;
unique
}
fn extend_unique_strings ( target : & mut Vec < String > , values : impl IntoIterator < Item = String > ) {
for value in values {
if ! target . iter ( ) . any ( | existing | existing = = & value ) {
target . push ( value ) ;
}
}
}
fn epiphany_active_subgoal_ids ( state : Option < & EpiphanyThreadState > ) -> Vec < String > {
state
. and_then ( | state | state . active_subgoal_id . clone ( ) )
. map ( | id | vec! [ id ] )
. unwrap_or_default ( )
}
fn epiphany_active_graph_node_ids ( state : Option < & EpiphanyThreadState > ) -> Vec < String > {
state
. and_then ( | state | state . graph_frontier . as_ref ( ) )
. map ( | frontier | frontier . active_node_ids . clone ( ) )
. unwrap_or_default ( )
}
#[ cfg(test) ]
mod tests {
use super ::* ;
2026-08-11 14:42:40 +02:00
#[ test ]
fn admitted_direction_schema_bounds_autonomous_proposal_fanout ( ) {
let schema = epiphany_admitted_model_direction_consideration_output_schema ( ) ;
assert_eq! (
2026-08-13 22:14:56 +02:00
schema [ " properties " ] [ " admittedModelDirectionConsiderationResult " ] [ " properties " ] [ " option_drafts " ]
[ " maxItems " ] ,
2026-08-11 14:42:40 +02:00
crate ::admitted_model_direction_consideration ::MAX_OPTION_DRAFTS
) ;
}
2026-07-12 00:41:05 +01:00
#[ test ]
fn live_worker_contracts_contain_no_codex_route_vocabulary ( ) {
let source = include_str! ( " agent_launch.rs " ) ;
let production = source . split ( " #[cfg(test)] " ) . next ( ) . unwrap_or ( source ) ;
assert! ( ! production . contains ( " thread/epiphany/ " ) ) ;
assert! ( production . contains ( " epiphany.coordinator.reorient.launch " ) ) ;
assert! ( production . contains ( " statePatch for Mind admission " ) ) ;
}
2026-05-28 21:02:26 +01:00
#[ test ]
fn bundled_epiphany_agent_prompts_do_not_name_codex_as_prompt_authority ( ) {
let prompts = epiphany_specialist_prompt_config ( ) ;
let rendered = [
(
" shared.persistent_memory " ,
prompts . shared . persistent_memory . as_str ( ) ,
) ,
( " roles.imagination " , prompts . roles . imagination . as_str ( ) ) ,
2026-07-15 03:05:11 +01:00
( " roles.mind " , prompts . roles . mind . as_str ( ) ) ,
2026-05-28 21:02:26 +01:00
( " roles.modeling " , prompts . roles . modeling . as_str ( ) ) ,
( " roles.verification " , prompts . roles . verification . as_str ( ) ) ,
( " roles.research " , prompts . roles . research . as_str ( ) ) ,
(
" roles.repo_personality " ,
prompts . roles . repo_personality . as_str ( ) ,
) ,
( " roles.repo_memory " , prompts . roles . repo_memory . as_str ( ) ) ,
2026-06-15 16:38:09 +01:00
( " roles.persona " , prompts . roles . persona . as_str ( ) ) ,
2026-05-28 21:02:26 +01:00
(
" implementation.continue_template " ,
prompts . implementation . continue_template . as_str ( ) ,
) ,
(
" reorientation.resume " ,
prompts . reorientation . resume . as_str ( ) ,
) ,
(
" reorientation.regather " ,
prompts . reorientation . regather . as_str ( ) ,
) ,
(
" coordinator.note_template " ,
prompts . coordinator . note_template . as_str ( ) ,
) ,
(
" crrc.pre_compaction_checkpoint_intervention " ,
prompts . crrc . pre_compaction_checkpoint_intervention . as_str ( ) ,
) ,
] ;
for ( name , prompt ) in rendered {
assert! (
! prompt . contains ( " Codex " ) ,
" {name} must stay Epiphany-owned and Codex-free "
) ;
}
}
#[ test ]
fn role_worker_prompt_is_bounded_not_full_persistent_memory ( ) {
let prompt = build_epiphany_role_launch_instruction ( EpiphanyRoleResultRoleId ::Modeling ) ;
assert! ( prompt . contains ( " Epiphany Worker Boundary " ) ) ;
assert! ( prompt . contains ( " Act as the Epiphany modeling/checkpoint specialist " ) ) ;
2026-07-16 16:49:45 +01:00
assert! ( prompt . contains ( " node `kind` is a closed vocabulary " ) ) ;
2026-05-28 21:02:26 +01:00
assert! ( ! prompt . contains ( " ## Epiphany Persistent Memory " ) ) ;
assert! ( ! prompt . contains ( " Heartbeat: every lane " ) ) ;
}
2026-08-07 05:21:32 +01:00
#[ test ]
fn role_self_patch_schema_matches_canonical_numeric_memory_contract ( ) {
let schema = epiphany_role_launch_output_schema ( EpiphanyRoleResultRoleId ::Verification ) ;
let self_patch = & schema [ " properties " ] [ " selfPatch " ] ;
for bundle in [
" semanticMemories " ,
" episodicMemories " ,
" relationshipMemories " ,
] {
let item = & self_patch [ " properties " ] [ bundle ] [ " items " ] ;
assert_eq! ( item [ " properties " ] [ " salience " ] [ " type " ] , " number " ) ;
assert_eq! ( item [ " properties " ] [ " confidence " ] [ " type " ] , " number " ) ;
assert_eq! ( item [ " additionalProperties " ] , false ) ;
}
assert_eq! (
self_patch [ " properties " ] [ " goals " ] [ " items " ] [ " properties " ] [ " priority " ] [ " type " ] ,
" number "
) ;
assert_eq! (
self_patch [ " properties " ] [ " values " ] [ " items " ] [ " properties " ] [ " priority " ] [ " type " ] ,
" number "
) ;
}
2026-08-13 22:14:56 +02:00
#[ test ]
fn research_schema_reuses_complete_typed_evidence_shapes ( ) {
let schema = epiphany_role_launch_output_schema ( EpiphanyRoleResultRoleId ::Research ) ;
let patch = & schema [ " properties " ] [ " statePatch " ] ;
let observation = & patch [ " properties " ] [ " observations " ] [ " items " ] ;
let evidence = & patch [ " properties " ] [ " evidence " ] [ " items " ] ;
assert_eq! ( patch [ " additionalProperties " ] , false ) ;
assert_eq! ( observation , & observation_output_schema ( ) ) ;
assert_eq! ( evidence , & evidence_output_schema ( ) ) ;
2026-08-14 16:19:35 +02:00
assert! (
observation [ " required " ]
. as_array ( )
. is_some_and ( | required | required . iter ( ) . any ( | field | field = = " source_kind " ) )
) ;
2026-08-13 22:14:56 +02:00
}
2026-07-15 01:29:35 +01:00
#[ test ]
fn frontier_planning_schema_exposes_candidate_without_generic_patch_mouths ( ) {
let schema = epiphany_frontier_planning_output_schema ( ) ;
2026-08-13 22:14:56 +02:00
assert! (
schema [ " properties " ]
. get ( " frontierPlanningRequestId " )
2026-08-14 16:19:35 +02:00
. is_none ( )
2026-08-13 22:14:56 +02:00
) ;
2026-07-15 01:29:35 +01:00
assert! ( schema [ " properties " ] . get ( " frontierPlanCandidate " ) . is_some ( ) ) ;
assert! ( schema [ " properties " ] . get ( " statePatch " ) . is_none ( ) ) ;
assert! ( schema [ " properties " ] . get ( " selfPatch " ) . is_none ( ) ) ;
assert! ( schema [ " properties " ] . get ( " repoModelPatch " ) . is_none ( ) ) ;
2026-08-14 16:19:35 +02:00
for runtime_owned in [
" planning_request_id " ,
" model_revision " ,
" model_hash " ,
" frontier_item_id " ,
" frontier_item_hash " ,
" proposed_at " ,
] {
assert! (
schema [ " properties " ] [ " frontierPlanCandidate " ] [ " properties " ]
. get ( runtime_owned )
. is_none ( )
) ;
}
2026-08-08 10:30:47 +01:00
assert! (
schema [ " properties " ] [ " frontierPlanCandidate " ] [ " properties " ] [ " safe_paths " ]
[ " description " ]
. as_str ( )
. is_some_and ( | description | description . contains ( " never add an adjacent " ) )
) ;
2026-07-15 01:29:35 +01:00
assert_eq! ( schema [ " additionalProperties " ] , false ) ;
}
2026-07-18 20:31:57 +01:00
#[ test ]
fn consideration_schema_has_only_proposal_candidate_cargo ( ) {
let schema = epiphany_imagination_consideration_output_schema ( ) ;
2026-08-13 22:14:56 +02:00
assert! (
schema [ " properties " ]
. get ( " imaginationConsiderationRequestId " )
. is_none ( )
) ;
assert! (
schema [ " properties " ]
. get ( " imaginationConsiderationCandidate " )
. is_some ( )
) ;
2026-08-11 05:22:53 +02:00
for runtime_owned in [
" request_id " ,
" feedback_id " ,
" feedback_packet_sha256 " ,
" source_room_id " ,
" source_visibility " ,
" data_classification " ,
" model_revision " ,
" model_hash " ,
2026-08-11 05:41:35 +02:00
" evidence_refs " ,
2026-08-11 05:22:53 +02:00
" proposed_at " ,
" contract " ,
] {
2026-08-13 22:14:56 +02:00
assert! (
schema [ " properties " ] [ " imaginationConsiderationCandidate " ] [ " properties " ]
. get ( runtime_owned )
. is_none ( )
) ;
2026-08-11 05:22:53 +02:00
}
2026-07-18 20:31:57 +01:00
for forbidden in [
" statePatch " ,
" selfPatch " ,
" repoModelPatch " ,
" frontierPlanCandidate " ,
] {
assert! ( schema [ " properties " ] . get ( forbidden ) . is_none ( ) ) ;
}
assert_eq! ( schema [ " additionalProperties " ] , false ) ;
}
2026-08-11 08:51:58 +02:00
#[ test ]
fn proposal_modeling_schema_exposes_only_strict_semantic_frontier_draft ( ) {
2026-08-13 22:14:56 +02:00
let schema =
epiphany_proposal_modeling_output_schema ( crate ::RepoFrontierProposalSourceKind ::User ) ;
2026-08-11 08:51:58 +02:00
assert_eq! ( schema [ " additionalProperties " ] , false ) ;
assert! ( schema [ " properties " ] . get ( " proposalFrontierDraft " ) . is_some ( ) ) ;
for runtime_owned in [
" repoModelPatch " ,
" proposalModelingRequestId " ,
" repositoryBodyObservationBasis " ,
" statePatch " ,
" selfPatch " ,
] {
assert! ( schema [ " properties " ] . get ( runtime_owned ) . is_none ( ) ) ;
}
let properties = schema [ " properties " ] . as_object ( ) . expect ( " root properties " ) ;
let required = schema [ " required " ] . as_array ( ) . expect ( " root required " ) ;
2026-08-13 22:14:56 +02:00
assert! (
properties
. keys ( )
. all ( | key | required . iter ( ) . any ( | item | item . as_str ( ) = = Some ( key ) ) )
) ;
2026-08-11 08:51:58 +02:00
let draft = & schema [ " properties " ] [ " proposalFrontierDraft " ] ;
let draft_properties = draft [ " properties " ] . as_object ( ) . expect ( " draft properties " ) ;
let draft_required = draft [ " required " ] . as_array ( ) . expect ( " draft required " ) ;
2026-08-13 22:14:56 +02:00
assert! (
draft_properties
. keys ( )
. all ( | key | draft_required . iter ( ) . any ( | item | item . as_str ( ) = = Some ( key ) ) )
) ;
2026-08-11 09:16:36 +02:00
fn every_const_has_a_type ( value : & serde_json ::Value ) -> bool {
match value {
serde_json ::Value ::Object ( map ) = > {
( ! map . contains_key ( " const " ) | | map . contains_key ( " type " ) )
& & map . values ( ) . all ( every_const_has_a_type )
}
serde_json ::Value ::Array ( values ) = > values . iter ( ) . all ( every_const_has_a_type ) ,
_ = > true ,
}
}
assert! ( every_const_has_a_type ( & schema ) ) ;
2026-08-11 08:51:58 +02:00
let imagination = epiphany_proposal_modeling_output_schema (
crate ::RepoFrontierProposalSourceKind ::Imagination ,
) ;
2026-08-18 00:34:51 +02:00
assert! (
! imagination [ " properties " ] [ " proposalFrontierDraft " ] [ " properties " ]
[ " recommendedNextOrgan " ] [ " enum " ]
. as_array ( )
. expect ( " organ enum " )
. iter ( )
. any ( | organ | organ = = " Hands " )
) ;
2026-08-11 08:51:58 +02:00
}
2026-05-28 21:02:26 +01:00
#[ test ]
fn reorient_worker_prompt_is_bounded_not_full_persistent_memory ( ) {
let prompt = build_epiphany_reorient_launch_instruction ( CoreEpiphanyReorientAction ::Resume ) ;
assert! ( prompt . contains ( " Epiphany Worker Boundary " ) ) ;
assert! ( ! prompt . contains ( " ## Epiphany Persistent Memory " ) ) ;
assert! ( ! prompt . contains ( " Heartbeat: every lane " ) ) ;
}
}