Bind Atlas Modeling to exact Body evidence

This commit is contained in:
Meta Vens 2026-08-14 17:24:25 +02:00
commit f60db0a206
17 changed files with 1968 additions and 208 deletions

View file

@ -138,6 +138,148 @@ fn repo_model_edge_output_schema() -> serde_json::Value {
})
}
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
}
]
})
}
fn code_ref_output_schema() -> serde_json::Value {
serde_json::json!({
"type": "object",
@ -519,7 +661,20 @@ pub fn epiphany_role_launch_output_schema(role_id: EpiphanyRoleResultRoleId) ->
{"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},
{"type": "object", "required": ["operation", "item"], "properties": {"operation": {"const": "put_frontier"}, "item": repo_frontier_item_output_schema()}, "additionalProperties": false}
{"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}
]
}
}),
@ -570,7 +725,7 @@ pub fn epiphany_role_launch_output_schema(role_id: EpiphanyRoleResultRoleId) ->
},
{
"if": {
"properties": {"verdict": {"enum": ["checkpoint-ready", "regather-needed"]}},
"properties": {"verdict": {"const": "regather-needed"}},
"required": ["verdict"]
},
"then": {
@ -1555,7 +1710,12 @@ mod tests {
"retire_node",
"put_edge",
"retire_edge",
"put_frontier"
"put_frontier",
"create_surface_offer",
"deprecate_surface_offer",
"withdraw_surface_offer",
"create_dependency_claim",
"retire_dependency_claim"
]
);
let node_kinds = operations[0]["properties"]["node"]["properties"]["kind"]["enum"]
@ -1568,6 +1728,24 @@ mod tests {
.get("created_at")
.is_none()
);
assert!(operations[5]["properties"].get("surface_id").is_none());
assert!(operations[8]["properties"].get("claim_id").is_none());
assert_eq!(
operations[5]["required"],
serde_json::json!(["operation", "label", "contract", "source_refs"])
);
assert_eq!(
operations[8]["required"],
serde_json::json!([
"operation",
"label",
"target",
"entanglement_kind",
"failure_semantics",
"impact_scope",
"source_refs"
])
);
assert_eq!(
schema["allOf"][0]["then"]["properties"]["repoModelOperations"]["maxContains"],
1

View file

@ -162,6 +162,30 @@ pub enum AtlasOfferLifecycle {
Withdrawn,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AtlasBodyEvidenceRef {
pub path: String,
pub raw_sha256: String,
}
impl AtlasBodyEvidenceRef {
pub fn validate(&self) -> Result<()> {
if self.path.is_empty()
|| self.path.len() > 1024
|| self.path.starts_with('/')
|| self.path.contains('\\')
|| self
.path
.split('/')
.any(|segment| segment.is_empty() || segment == "." || segment == "..")
{
bail!("Atlas Body evidence path is not a canonical portable relative path")
}
validate_repository_body_sha256(&self.raw_sha256, "Atlas Body evidence raw content digest")
}
}
#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "gamecult.model.surface_offer.v0",
@ -178,6 +202,10 @@ pub struct AtlasSurfaceOffer {
pub contract: AtlasContractDescriptor,
#[cultcache(key = 4)]
pub lifecycle: AtlasOfferLifecycle,
#[cultcache(key = 5)]
pub label: String,
#[cultcache(key = 6)]
pub body_evidence: Vec<AtlasBodyEvidenceRef>,
}
impl AtlasSurfaceOffer {
@ -188,6 +216,7 @@ impl AtlasSurfaceOffer {
bail!("Atlas surface id must be an opaque non-nil UUID")
}
self.contract.validate()?;
validate_label_and_body_evidence(&self.label, &self.body_evidence, "Atlas surface offer")?;
if matches!(
self.lifecycle,
AtlasOfferLifecycle::Deprecated {
@ -297,6 +326,10 @@ pub struct AtlasDependencyClaim {
pub impact_scope: AtlasImpactScope,
#[cultcache(key = 7)]
pub lifecycle: AtlasClaimLifecycle,
#[cultcache(key = 8)]
pub label: String,
#[cultcache(key = 9)]
pub body_evidence: Vec<AtlasBodyEvidenceRef>,
}
impl AtlasDependencyClaim {
@ -308,6 +341,11 @@ impl AtlasDependencyClaim {
}
self.target.validate()?;
self.impact_scope.validate()?;
validate_label_and_body_evidence(
&self.label,
&self.body_evidence,
"Atlas dependency claim",
)?;
if let AtlasDependencyTarget::Exact { provider, .. } = &self.target {
if provider == &self.consumer {
bail!("Atlas dependency claim cannot target its owning repository")
@ -681,9 +719,16 @@ pub enum AtlasVerificationState {
#[serde(rename_all = "camelCase")]
pub struct AtlasProjectedEntanglement {
pub claim_id: Uuid,
pub claim_label: String,
pub claim_requirement: AtlasContractRequirement,
pub claim_body_evidence: Vec<AtlasBodyEvidenceRef>,
pub consumer: AtlasRepositoryIdentity,
pub provider: Option<AtlasRepositoryIdentity>,
pub surface_id: Option<Uuid>,
pub offer_label: Option<String>,
pub offer_contract: Option<AtlasContractDescriptor>,
pub offer_lifecycle: Option<AtlasOfferLifecycle>,
pub offer_body_evidence: Vec<AtlasBodyEvidenceRef>,
pub entanglement_kind: AtlasEntanglementKind,
pub failure_semantics: AtlasFailureSemantics,
pub impact_scope: AtlasImpactScope,
@ -693,6 +738,8 @@ pub struct AtlasProjectedEntanglement {
pub verification: AtlasVerificationState,
pub claim_publication_id: String,
pub offer_publication_id: Option<String>,
pub verification_publication_id: Option<String>,
pub verification_evidence_sha256: Option<String>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
@ -827,6 +874,23 @@ fn strictly_sorted_unique<T: Ord>(values: &[T]) -> bool {
values.windows(2).all(|pair| pair[0] < pair[1])
}
fn validate_label_and_body_evidence(
label: &str,
evidence: &[AtlasBodyEvidenceRef],
field: &str,
) -> Result<()> {
if label.trim().is_empty() || label.len() > 320 {
bail!("{field} label must be non-empty and bounded")
}
if evidence.is_empty() || !strictly_sorted_unique(evidence) {
bail!("{field} Body evidence must be a non-empty strictly sorted set")
}
for source in evidence {
source.validate()?;
}
Ok(())
}
pub(crate) fn canonical_entanglement_kinds(
kinds: impl IntoIterator<Item = AtlasEntanglementKind>,
) -> Vec<AtlasEntanglementKind> {

View file

@ -6,10 +6,10 @@ use cultcache_rs::DatabaseEntry;
use serde::{Deserialize, Serialize};
use super::contracts::{
ATLAS_PROJECTION_SCHEMA, AtlasCompatibility, AtlasEntanglementKind,
AtlasEntanglementProjection, AtlasFailureSemantics, AtlasImpactScope,
AtlasProjectedEntanglement, AtlasPublicationFreshness, AtlasRepositoryIdentity,
AtlasVerificationState,
ATLAS_PROJECTION_SCHEMA, AtlasBodyEvidenceRef, AtlasCompatibility, AtlasContractDescriptor,
AtlasContractRequirement, AtlasCycleClass, AtlasEntanglementKind, AtlasEntanglementProjection,
AtlasFailureSemantics, AtlasImpactScope, AtlasOfferLifecycle, AtlasProjectedEntanglement,
AtlasPublicationFreshness, AtlasRepositoryIdentity, AtlasVerificationState,
};
use super::projector::atlas_projection_digest;
@ -503,7 +503,7 @@ fn surface_document(
state_bindings: Vec::new(),
children: vec![
attention_component(projection, presentation, selected_id, options),
drilldown_component(selected),
drilldown_component(projection, selected),
graph_component(projection),
],
},
@ -527,7 +527,7 @@ fn attention_component(
.attention_filter
.accepts(entanglement_state(edge))
})
.map(entanglement_item)
.map(|edge| entanglement_item(projection, edge))
.collect();
EveComponent {
@ -607,19 +607,24 @@ fn attention_component(
}
}
fn drilldown_component(selected: Option<&AtlasProjectedEntanglement>) -> EveComponent {
fn drilldown_component(
projection: &AtlasEntanglementProjection,
selected: Option<&AtlasProjectedEntanglement>,
) -> EveComponent {
let title = selected
.map(entanglement_label)
.unwrap_or_else(|| "Selected entanglement".into());
let summary = selected
.map(entanglement_summary)
.map(|edge| entanglement_summary(projection, edge))
.unwrap_or_else(|| "No entanglement is present in the current projection.".into());
let status = selected
.map(entanglement_state)
.map(AtlasEveEntanglementState::as_wire_name)
.unwrap_or("empty");
let claims = selected.map(claim_items).unwrap_or_default();
let evidence = selected.map(evidence_items).unwrap_or_default();
let evidence = selected
.map(|edge| evidence_items(projection, edge))
.unwrap_or_default();
EveComponent {
id: MODEL_ATLAS_DRILLDOWN_ID.into(),
@ -705,7 +710,7 @@ fn graph_component(projection: &AtlasEntanglementProjection) -> EveComponent {
let linear_items = projection
.entanglements
.iter()
.map(entanglement_item)
.map(|edge| entanglement_item(projection, edge))
.collect();
EveComponent {
@ -821,7 +826,8 @@ fn repository_node_id(repository: &AtlasRepositoryIdentity) -> String {
fn entanglement_label(edge: &AtlasProjectedEntanglement) -> String {
format!(
"{} -> {}",
"{}: {} -> {}",
edge.claim_label,
edge.consumer.workspace_id,
edge.provider
.as_ref()
@ -830,9 +836,15 @@ fn entanglement_label(edge: &AtlasProjectedEntanglement) -> String {
)
}
fn entanglement_summary(edge: &AtlasProjectedEntanglement) -> String {
fn entanglement_summary(
projection: &AtlasEntanglementProjection,
edge: &AtlasProjectedEntanglement,
) -> String {
let publisher_age = entanglement_publisher_age_ms(projection, edge)
.map(|age_ms| format!("{age_ms} ms"))
.unwrap_or_else(|| "unknown".into());
format!(
"{} dependency; failure semantics {}; compatibility {}; verification {}; claim freshness {}; offer freshness {}.",
"{} dependency; failure semantics {}; compatibility {}; verification {}; claim freshness {}; offer freshness {}; publisher age {}.",
entanglement_kind_name(edge.entanglement_kind),
failure_semantics_name(edge.failure_semantics),
compatibility_name(edge.compatibility),
@ -841,14 +853,18 @@ fn entanglement_summary(edge: &AtlasProjectedEntanglement) -> String {
edge.offer_freshness
.map(freshness_name)
.unwrap_or("missing"),
publisher_age,
)
}
fn entanglement_item(edge: &AtlasProjectedEntanglement) -> EveListItem {
fn entanglement_item(
projection: &AtlasEntanglementProjection,
edge: &AtlasProjectedEntanglement,
) -> EveListItem {
EveListItem {
label: entanglement_label(edge),
status: entanglement_state(edge).as_wire_name().into(),
detail: entanglement_summary(edge),
detail: entanglement_summary(projection, edge),
badges: vec![
entanglement_kind_name(edge.entanglement_kind).into(),
failure_semantics_name(edge.failure_semantics).into(),
@ -858,21 +874,26 @@ fn entanglement_item(edge: &AtlasProjectedEntanglement) -> EveListItem {
fn claim_items(edge: &AtlasProjectedEntanglement) -> Vec<EveListItem> {
let mut items = vec![EveListItem {
label: "Consumer claim".into(),
label: format!("Consumer claim: {}", edge.claim_label),
status: freshness_name(edge.claim_freshness).into(),
detail: format!(
"{} owns claim {} from publication {} with {} impact scope.",
"{} owns claim {} from publication {} with {} impact scope; requires {}; Body evidence {}.",
edge.consumer.repository_uri,
edge.claim_id,
edge.claim_publication_id,
impact_scope_name(&edge.impact_scope),
contract_requirement_name(&edge.claim_requirement),
body_evidence_name(&edge.claim_body_evidence),
),
badges: vec![edge.consumer.workspace_id.clone()],
}];
if let Some(provider) = &edge.provider {
items.push(EveListItem {
label: "Provider offer".into(),
label: format!(
"Provider offer: {}",
edge.offer_label.as_deref().unwrap_or("missing")
),
status: edge
.offer_freshness
.map(freshness_name)
@ -880,8 +901,19 @@ fn claim_items(edge: &AtlasProjectedEntanglement) -> Vec<EveListItem> {
.into(),
detail: match (&edge.surface_id, &edge.offer_publication_id) {
(Some(surface_id), Some(publication_id)) => format!(
"{} owns surface {} from publication {}.",
provider.repository_uri, surface_id, publication_id
"{} owns surface {} from publication {}; contract {}; lifecycle {}; Body evidence {}.",
provider.repository_uri,
surface_id,
publication_id,
edge.offer_contract
.as_ref()
.map(contract_descriptor_name)
.unwrap_or_else(|| "missing".into()),
edge.offer_lifecycle
.as_ref()
.map(offer_lifecycle_name)
.unwrap_or("missing"),
body_evidence_name(&edge.offer_body_evidence),
),
_ => format!(
"{} has no admitted offer for this claim.",
@ -895,27 +927,161 @@ fn claim_items(edge: &AtlasProjectedEntanglement) -> Vec<EveListItem> {
items
}
fn evidence_items(edge: &AtlasProjectedEntanglement) -> Vec<EveListItem> {
vec![
fn evidence_items(
projection: &AtlasEntanglementProjection,
edge: &AtlasProjectedEntanglement,
) -> Vec<EveListItem> {
let mut items = vec![
EveListItem {
label: "Compatibility".into(),
status: compatibility_name(edge.compatibility).into(),
detail: format!(
"Epiphany Modeling derived {} from the admitted claim and offer publications.",
compatibility_name(edge.compatibility)
"Epiphany Modeling compared requirement {} with offer {} and derived {}.",
contract_requirement_name(&edge.claim_requirement),
edge.offer_contract
.as_ref()
.map(contract_descriptor_name)
.unwrap_or_else(|| "missing".into()),
compatibility_name(edge.compatibility),
),
badges: vec!["modeling".into()],
},
EveListItem {
label: "Soul verification".into(),
status: verification_name(edge.verification).into(),
detail: format!(
"Exact claim/offer verification state is {}.",
verification_name(edge.verification)
),
detail: match (
&edge.verification_publication_id,
&edge.verification_evidence_sha256,
) {
(Some(publication), Some(evidence)) => format!(
"Exact claim/offer verification state is {}; publication {}; evidence {}.",
verification_name(edge.verification),
publication,
evidence,
),
_ => format!(
"Exact claim/offer verification state is {}; no current exact Soul evidence applies.",
verification_name(edge.verification)
),
},
badges: vec!["soul".into()],
},
]
];
let cycle_memberships = projection
.cycles
.iter()
.filter(|cycle| {
cycle
.repositories
.iter()
.any(|repository| repository == &edge.consumer)
&& edge.provider.as_ref().is_some_and(|provider| {
cycle
.repositories
.iter()
.any(|repository| repository == provider)
})
&& cycle.entanglement_kinds.contains(&edge.entanglement_kind)
})
.map(|cycle| cycle_class_name(cycle.classification))
.collect::<Vec<_>>();
items.push(EveListItem {
label: "Cycle membership".into(),
status: if cycle_memberships.is_empty() {
"none".into()
} else {
"present".into()
},
detail: if cycle_memberships.is_empty() {
"This edge is not a member of a projected cycle.".into()
} else {
format!(
"Projected cycle classes: {}.",
cycle_memberships.join(" | ")
)
},
badges: vec!["projector".into()],
});
let radius = edge.provider.as_ref().and_then(|provider| {
edge.surface_id.and_then(|surface_id| {
projection
.blast_radii
.iter()
.find(|radius| radius.source == *provider && radius.source_surface_id == surface_id)
})
});
items.push(EveListItem {
label: "Blast radius".into(),
status: radius.map(|_| "derived").unwrap_or("none").into(),
detail: radius
.map(|radius| {
radius
.affected
.iter()
.map(|affected| {
format!(
"{}:{} hop(s)",
affected.repository.workspace_id, affected.minimum_hops
)
})
.collect::<Vec<_>>()
.join(" | ")
})
.filter(|detail| !detail.is_empty())
.unwrap_or_else(|| "No downstream repository is projected from this surface.".into()),
badges: vec!["projector".into()],
});
let watermarks = projection
.publisher_status
.iter()
.filter(|status| {
status.publisher == edge.consumer
|| edge
.provider
.as_ref()
.is_some_and(|provider| status.publisher == *provider)
})
.map(|status| {
format!(
"{} heartbeat={} age_ms={} documents={}",
status.publisher.workspace_id,
status.heartbeat_sequence,
projection
.evaluated_at_unix_ms
.saturating_sub(status.heartbeat_at_unix_ms),
status.watermarks.len()
)
})
.collect::<Vec<_>>();
items.push(EveListItem {
label: "Publisher watermarks".into(),
status: "bounded".into(),
detail: watermarks.join(" | "),
badges: vec!["odin".into()],
});
items
}
fn entanglement_publisher_age_ms(
projection: &AtlasEntanglementProjection,
edge: &AtlasProjectedEntanglement,
) -> Option<u64> {
projection
.publisher_status
.iter()
.filter(|status| {
status.publisher == edge.consumer
|| edge
.provider
.as_ref()
.is_some_and(|provider| status.publisher == *provider)
})
.map(|status| {
projection
.evaluated_at_unix_ms
.saturating_sub(status.heartbeat_at_unix_ms)
})
.max()
}
fn graph_values(
@ -1137,6 +1303,66 @@ fn impact_scope_name(scope: &AtlasImpactScope) -> String {
}
}
fn contract_descriptor_name(contract: &AtlasContractDescriptor) -> String {
match contract {
AtlasContractDescriptor::Semver {
contract_id,
version,
} => format!("semver:{contract_id}@{version}"),
AtlasContractDescriptor::ExactSchema {
contract_id,
schema_id,
} => format!("exact_schema:{contract_id}@{schema_id}"),
AtlasContractDescriptor::ExactDigest {
contract_id,
sha256,
} => format!("exact_digest:{contract_id}@{sha256}"),
}
}
fn contract_requirement_name(requirement: &AtlasContractRequirement) -> String {
match requirement {
AtlasContractRequirement::Semver {
contract_id,
requirement,
} => format!("semver:{contract_id}@{requirement}"),
AtlasContractRequirement::ExactSchema {
contract_id,
schema_id,
} => format!("exact_schema:{contract_id}@{schema_id}"),
AtlasContractRequirement::ExactDigest {
contract_id,
sha256,
} => format!("exact_digest:{contract_id}@{sha256}"),
}
}
fn offer_lifecycle_name(lifecycle: &AtlasOfferLifecycle) -> &'static str {
match lifecycle {
AtlasOfferLifecycle::Active => "active",
AtlasOfferLifecycle::Deprecated { .. } => "deprecated",
AtlasOfferLifecycle::Withdrawn => "withdrawn",
}
}
fn body_evidence_name(evidence: &[AtlasBodyEvidenceRef]) -> String {
evidence
.iter()
.map(|source| format!("{}@{}", source.path, source.raw_sha256))
.collect::<Vec<_>>()
.join(" | ")
}
fn cycle_class_name(classification: AtlasCycleClass) -> &'static str {
match classification {
AtlasCycleClass::ForbiddenBuild => "forbidden_build",
AtlasCycleClass::ForbiddenDeployment => "forbidden_deployment",
AtlasCycleClass::ForbiddenInfrastructureControl => "forbidden_infrastructure_control",
AtlasCycleClass::ReviewRequired => "review_required",
AtlasCycleClass::Informational => "informational",
}
}
fn is_false(value: &bool) -> bool {
!*value
}
@ -1170,9 +1396,28 @@ mod tests {
fn edge(compatibility: AtlasCompatibility) -> AtlasProjectedEntanglement {
AtlasProjectedEntanglement {
claim_id: Uuid::from_u128(7),
claim_label: "Epiphany consumes Eve".into(),
claim_requirement: AtlasContractRequirement::ExactSchema {
contract_id: "eve-surface".into(),
schema_id: "gamecult.eve.surface.v1".into(),
},
claim_body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
consumer: repository("epiphany"),
provider: Some(repository("eve")),
surface_id: Some(Uuid::from_u128(9)),
offer_label: Some("Canonical Eve surface".into()),
offer_contract: Some(AtlasContractDescriptor::ExactSchema {
contract_id: "eve-surface".into(),
schema_id: "gamecult.eve.surface.v1".into(),
}),
offer_lifecycle: Some(AtlasOfferLifecycle::Active),
offer_body_evidence: vec![AtlasBodyEvidenceRef {
path: "schemas/gamecult.eve.surface.v1.schema.json".into(),
raw_sha256: "1".repeat(64),
}],
entanglement_kind: AtlasEntanglementKind::SchemaProtocol,
failure_semantics: AtlasFailureSemantics::HumanDecision,
impact_scope: AtlasImpactScope::WholeRepository,
@ -1182,6 +1427,8 @@ mod tests {
verification: AtlasVerificationState::Passed,
claim_publication_id: format!("sha256-{}", "1".repeat(64)),
offer_publication_id: Some(format!("sha256-{}", "2".repeat(64))),
verification_publication_id: Some(format!("sha256-{}", "3".repeat(64))),
verification_evidence_sha256: Some(format!("sha256-{}", "4".repeat(64))),
}
}
@ -1249,6 +1496,43 @@ mod tests {
assert_eq!(root.children[2].children[0].kind, "list");
}
#[test]
fn attention_and_drilldown_report_the_oldest_endpoint_publisher_age() {
let mut projection = projection_with(vec![edge(AtlasCompatibility::Compatible)]);
projection.publisher_status = vec![
crate::AtlasPublisherProjectionStatus {
publisher: repository("epiphany"),
runtime_id: "epiphany-runtime".into(),
runtime_incarnation_id: "epiphany-incarnation".into(),
heartbeat_sequence: 3,
heartbeat_at_unix_ms: projection.evaluated_at_unix_ms - 250,
freshness: AtlasPublicationFreshness::Current,
watermarks: Vec::new(),
status_publication_id: format!("sha256-{}", "5".repeat(64)),
},
crate::AtlasPublisherProjectionStatus {
publisher: repository("eve"),
runtime_id: "eve-runtime".into(),
runtime_incarnation_id: "eve-incarnation".into(),
heartbeat_sequence: 7,
heartbeat_at_unix_ms: projection.evaluated_at_unix_ms - 900,
freshness: AtlasPublicationFreshness::Current,
watermarks: Vec::new(),
status_publication_id: format!("sha256-{}", "6".repeat(64)),
},
];
let summary = entanglement_summary(&projection, &projection.entanglements[0]);
assert!(summary.contains("publisher age 900 ms"));
let evidence = evidence_items(&projection, &projection.entanglements[0]);
assert!(
evidence
.iter()
.find(|item| item.label == "Publisher watermarks")
.is_some_and(|item| item.detail.contains("age_ms=900"))
);
}
#[test]
fn every_binding_reads_the_owned_projection_and_commands_are_presentation_only() {
let documents = project_model_atlas_eve_documents(

View file

@ -520,6 +520,13 @@ mod tests {
sha256(seed.as_bytes())
}
fn body_evidence() -> Vec<AtlasBodyEvidenceRef> {
vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}]
}
fn repository(workspace: &str) -> AtlasRepositoryIdentity {
AtlasRepositoryIdentity::new("swarm", workspace).unwrap()
}
@ -541,6 +548,8 @@ mod tests {
failure_semantics: AtlasFailureSemantics::Degrade,
impact_scope: AtlasImpactScope::WholeRepository,
lifecycle: AtlasClaimLifecycle::Active,
label: "Consumer runtime dependency".into(),
body_evidence: body_evidence(),
}
}
@ -562,9 +571,22 @@ mod tests {
) -> AtlasProjectedEntanglement {
AtlasProjectedEntanglement {
claim_id: Uuid::from_u128(1),
claim_label: "Consumer runtime dependency".into(),
claim_requirement: AtlasContractRequirement::ExactSchema {
contract_id: "contract.surface".into(),
schema_id: "schema.surface.v1".into(),
},
claim_body_evidence: body_evidence(),
consumer: repository("consumer"),
provider: Some(repository("provider")),
surface_id: Some(Uuid::from_u128(2)),
offer_label: Some("Provider runtime surface".into()),
offer_contract: Some(AtlasContractDescriptor::ExactSchema {
contract_id: "contract.surface".into(),
schema_id: "schema.surface.v1".into(),
}),
offer_lifecycle: Some(AtlasOfferLifecycle::Active),
offer_body_evidence: body_evidence(),
entanglement_kind: AtlasEntanglementKind::Runtime,
failure_semantics: AtlasFailureSemantics::Degrade,
impact_scope: AtlasImpactScope::WholeRepository,
@ -574,6 +596,13 @@ mod tests {
verification,
claim_publication_id: digest("claim-publication"),
offer_publication_id: Some(digest("offer-publication")),
verification_publication_id: (!matches!(verification, AtlasVerificationState::Missing))
.then(|| digest("verification-publication")),
verification_evidence_sha256: (!matches!(
verification,
AtlasVerificationState::Missing
))
.then(|| digest("verification-evidence")),
}
}

View file

@ -1246,6 +1246,11 @@ mod tests {
surface_id,
contract: descriptor("2.1.0"),
lifecycle: AtlasOfferLifecycle::Active,
label: "Test surface".into(),
body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
}
}
@ -1268,6 +1273,11 @@ mod tests {
failure_semantics: AtlasFailureSemantics::HumanDecision,
impact_scope: AtlasImpactScope::WholeRepository,
lifecycle: AtlasClaimLifecycle::Active,
label: "Test dependency".into(),
body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
}
}
@ -1499,9 +1509,19 @@ mod tests {
publisher_status: Vec::new(),
entanglements: vec![AtlasProjectedEntanglement {
claim_id,
claim_label: claim_read.document.label.clone(),
claim_requirement: claim_read.document.target.requirement().clone(),
claim_body_evidence: claim_read.document.body_evidence.clone(),
consumer: consumer.identity.clone(),
provider: Some(provider.identity.clone()),
surface_id: Some(surface_id),
offer_label: Some("Provider surface".into()),
offer_contract: Some(descriptor("2.1.0")),
offer_lifecycle: Some(AtlasOfferLifecycle::Active),
offer_body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
entanglement_kind: AtlasEntanglementKind::Runtime,
failure_semantics: AtlasFailureSemantics::HumanDecision,
impact_scope: AtlasImpactScope::WholeRepository,
@ -1511,6 +1531,8 @@ mod tests {
verification: AtlasVerificationState::Missing,
claim_publication_id,
offer_publication_id: Some(offer_publication_id),
verification_publication_id: None,
verification_evidence_sha256: None,
}],
cycles: Vec::new(),
blast_radii: Vec::new(),

View file

@ -137,13 +137,22 @@ pub fn project_atlas(
_ => None,
});
let compatibility = evaluate_atlas_compatibility(claim, offer);
let verification = evaluate_verification(
accepted_claim,
accepted_offer,
verifications
.get(&(claim.consumer.repository_uri.clone(), claim.claim_id))
.copied(),
);
let accepted_verification = verifications
.get(&(claim.consumer.repository_uri.clone(), claim.claim_id))
.copied();
let verification =
evaluate_verification(accepted_claim, accepted_offer, accepted_verification);
let exact_verification = accepted_verification.filter(|_| {
!matches!(
verification,
AtlasVerificationState::Missing | AtlasVerificationState::ExactEdgeMismatch
)
});
let verification_document =
exact_verification.and_then(|accepted| match &accepted.publication.statement.payload {
AtlasPublicationPayload::DependencyVerification(verification) => Some(verification),
_ => None,
});
// The consumer's active exact claim owns dependency truth. Missing,
// withdrawn, or incompatible provider state changes compatibility; it
// must not erase the claimed edge or its transitive blast radius.
@ -160,9 +169,18 @@ pub fn project_atlas(
}
entanglements.push(AtlasProjectedEntanglement {
claim_id: claim.claim_id,
claim_label: claim.label.clone(),
claim_requirement: claim.target.requirement().clone(),
claim_body_evidence: claim.body_evidence.clone(),
consumer: claim.consumer.clone(),
provider: exact_target.map(|(provider, _, _)| provider.clone()),
surface_id: exact_target.map(|(_, surface_id, _)| surface_id),
offer_label: offer.map(|offer| offer.label.clone()),
offer_contract: offer.map(|offer| offer.contract.clone()),
offer_lifecycle: offer.map(|offer| offer.lifecycle.clone()),
offer_body_evidence: offer
.map(|offer| offer.body_evidence.clone())
.unwrap_or_default(),
entanglement_kind: claim.entanglement_kind,
failure_semantics: claim.failure_semantics,
impact_scope: claim.impact_scope.clone(),
@ -173,6 +191,10 @@ pub fn project_atlas(
claim_publication_id: accepted_claim.publication.statement.publication_id.clone(),
offer_publication_id: accepted_offer
.map(|offer| offer.publication.statement.publication_id.clone()),
verification_publication_id: exact_verification
.map(|accepted| accepted.publication.statement.publication_id.clone()),
verification_evidence_sha256: verification_document
.map(|verification| verification.evidence_sha256.clone()),
});
}
entanglements.sort_by(|left, right| {
@ -856,6 +878,11 @@ mod tests {
schema_id: schema_id.into(),
},
lifecycle: AtlasOfferLifecycle::Active,
label: "Exact schema offer".into(),
body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
})
}
@ -885,6 +912,11 @@ mod tests {
failure_semantics: AtlasFailureSemantics::HumanDecision,
impact_scope,
lifecycle: AtlasClaimLifecycle::Active,
label: "Exact schema dependency".into(),
body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
})
}

View file

@ -375,6 +375,11 @@ mod tests {
version: Version::new(1, 0, 0),
},
lifecycle: AtlasOfferLifecycle::Active,
label: "Published surface".into(),
body_evidence: vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: "0".repeat(64),
}],
});
let payload_sha256 = sha256(&atlas_source_payload_msgpack(&payload).unwrap());
let source = AtlasMindSourceVersion {

View file

@ -115,17 +115,20 @@ struct LocalClaimRead {
pub struct RuntimeAtlasMindSnapshotSource {
runtime_store: PathBuf,
repository: AtlasRepositoryIdentity,
body_basis: crate::RepositoryBodyObservationBasis,
}
impl RuntimeAtlasMindSnapshotSource {
pub fn new(
runtime_store: impl Into<PathBuf>,
repository: AtlasRepositoryIdentity,
body_basis: crate::RepositoryBodyObservationBasis,
) -> Result<Self> {
repository.validate()?;
Ok(Self {
runtime_store: runtime_store.into(),
repository,
body_basis,
})
}
}
@ -134,6 +137,13 @@ impl AtlasLocalMindSnapshotSource for RuntimeAtlasMindSnapshotSource {
fn load_local_atlas_mind_snapshot(&self) -> Result<AtlasLocalMindSnapshot> {
let mut cache = crate::runtime_spine_cache(&self.runtime_store)?;
cache.pull_all_backing_stores()?;
if crate::load_current_runtime_repository_body_basis(&self.runtime_store)?
!= self.body_basis
{
bail!("Atlas publisher lost its exact current Repository Body basis")
}
let manifest =
crate::authenticated_repository_body_manifest(&self.runtime_store, &self.body_basis)?;
let snapshot = cache.snapshot_envelopes();
let receipts = snapshot
.iter()
@ -169,6 +179,7 @@ impl AtlasLocalMindSnapshotSource for RuntimeAtlasMindSnapshotSource {
{
bail!("local Atlas Mind document has foreign ownership or a substituted key")
}
validate_atlas_body_evidence_for_manifest(&payload, &manifest)?;
let source = atlas_source_for_payload("epiphany-mind", &payload)?;
let receipt = latest_exact_mind_commit(&receipts, &envelope)?;
let mind_commit = AtlasMindCommitBinding {
@ -195,6 +206,39 @@ impl AtlasLocalMindSnapshotSource for RuntimeAtlasMindSnapshotSource {
}
}
fn validate_atlas_body_evidence_for_manifest(
payload: &AtlasPublicationPayload,
manifest: &crate::RepositoryBodyManifest,
) -> Result<()> {
let evidence = match payload {
AtlasPublicationPayload::SurfaceOffer(offer) => &offer.body_evidence,
AtlasPublicationPayload::DependencyClaim(claim) => &claim.body_evidence,
AtlasPublicationPayload::DependencyVerification(_) => return Ok(()),
AtlasPublicationPayload::PublisherStatus(_) => return Ok(()),
};
let entries = manifest
.entries
.iter()
.map(|entry| (entry.path.as_str(), entry))
.collect::<std::collections::BTreeMap<_, _>>();
for source in evidence {
source.validate()?;
let entry = entries.get(source.path.as_str()).ok_or_else(|| {
anyhow::anyhow!(
"Atlas Body evidence path {:?} is absent from the current manifest",
source.path
)
})?;
if entry.kind != "regular" || entry.raw_sha256 != source.raw_sha256 {
bail!(
"Atlas Body evidence path {:?} no longer has its admitted content",
source.path
)
}
}
Ok(())
}
pub fn run_atlas_publisher_once(
config: &AtlasPublisherRunConfig,
) -> Result<AtlasPublisherRunOutcome> {
@ -224,8 +268,11 @@ pub fn run_atlas_publisher_once(
let store = AtlasCultCacheStore::new(&config.publisher_store, config.repository.clone())?;
ensure_local_publisher_trust(&store, &signer, config.now_unix_ms)?;
let heartbeat_sequence = next_heartbeat_sequence(&store)?;
let mind =
RuntimeAtlasMindSnapshotSource::new(&config.runtime_mind_store, config.repository.clone())?;
let mind = RuntimeAtlasMindSnapshotSource::new(
&config.runtime_mind_store,
config.repository.clone(),
body_basis.clone(),
)?;
let adapter = AtlasPublisherSnapshotAdapter::new(&mind, &store);
let batch = publish_local_atlas_state(
&adapter,
@ -1119,6 +1166,11 @@ mod tests {
crate::runtime_spine::tests::bind_test_runtime_swarm(&store, "swarm")?;
crate::runtime_spine::tests::bind_test_repository_body(&store, "workspace")?;
let body = crate::observe_runtime_repository_body_basis(&store)?;
let manifest = crate::authenticated_repository_body_manifest(&store, &body)?;
let body_evidence = vec![AtlasBodyEvidenceRef {
path: manifest.entries[0].path.clone(),
raw_sha256: manifest.entries[0].raw_sha256.clone(),
}];
let local = AtlasRepositoryIdentity::new("swarm", "workspace")?;
let provider = AtlasRepositoryIdentity::new("swarm", "provider")?;
@ -1131,6 +1183,8 @@ mod tests {
version: Version::parse("1.0.0")?,
},
lifecycle: AtlasOfferLifecycle::Active,
label: "Local contract surface".into(),
body_evidence: body_evidence.clone(),
};
let offer_intent = admit_surface_offer(AtlasSurfaceOfferAdmissionInput {
context: AtlasPlannerContext {
@ -1160,6 +1214,8 @@ mod tests {
failure_semantics: AtlasFailureSemantics::FailClosed,
impact_scope: AtlasImpactScope::WholeRepository,
lifecycle: AtlasClaimLifecycle::Active,
label: "Provider runtime dependency".into(),
body_evidence: body_evidence.clone(),
};
let claim_intent = admit_dependency_claim(AtlasDependencyClaimAdmissionInput {
context: AtlasPlannerContext {
@ -1270,6 +1326,8 @@ mod tests {
version: Version::parse("1.2.0")?,
},
lifecycle: AtlasOfferLifecycle::Active,
label: "Provider contract surface".into(),
body_evidence,
};
let mut provider_body = body.clone();
provider_body.workspace_id = provider.workspace_id.clone();
@ -1336,6 +1394,16 @@ mod tests {
)?,
crate::EpiphanyMindCommitOutcome::Committed(_)
));
std::fs::write(
store
.with_extension("workspace.body-repo")
.join("body-seed.txt"),
b"changed provider evidence",
)?;
let changed_body = crate::observe_runtime_repository_body_basis(&store)?;
let stale_source = RuntimeAtlasMindSnapshotSource::new(&store, local, changed_body)?;
assert!(stale_source.load_local_atlas_mind_snapshot().is_err());
Ok(())
}
}

View file

@ -25,6 +25,13 @@ fn body_digest(seed: &str) -> String {
digest(seed).trim_start_matches("sha256-").to_owned()
}
fn body_evidence() -> Vec<AtlasBodyEvidenceRef> {
vec![AtlasBodyEvidenceRef {
path: "Cargo.toml".into(),
raw_sha256: body_digest("atlas-test-source"),
}]
}
fn repo(temp: &TempDir, ordinal: u128, name: &str) -> Result<Repo> {
let identity = AtlasRepositoryIdentity::new("gamecult", format!("workspace-{name}"))?;
let signer = enroll_service_identity_at::<AtlasRepositorySigningIdentity>(
@ -85,6 +92,8 @@ fn offer_payload(provider: &Repo, surface_id: Uuid, version: &str) -> AtlasPubli
surface_id,
contract: semver_descriptor("contract:api", version),
lifecycle: AtlasOfferLifecycle::Active,
label: "API surface".into(),
body_evidence: body_evidence(),
})
}
@ -118,6 +127,8 @@ fn claim_payload(
},
impact_scope: AtlasImpactScope::WholeRepository,
lifecycle: AtlasClaimLifecycle::Active,
label: "API dependency".into(),
body_evidence: body_evidence(),
})
}
@ -249,6 +260,8 @@ fn three_repo_vertical_slice_wakes_direct_then_transitive_modeling() -> Result<(
schema_id: schema_id.into(),
},
lifecycle: AtlasOfferLifecycle::Active,
label: format!("{} surface", owner.identity.workspace_id),
body_evidence: body_evidence(),
})
};
let eve_offer = mind_publication(
@ -289,6 +302,8 @@ fn three_repo_vertical_slice_wakes_direct_then_transitive_modeling() -> Result<(
surface_ids: vec![odin_catalog],
},
lifecycle: AtlasClaimLifecycle::Active,
label: "Odin consumes Eve surface".into(),
body_evidence: body_evidence(),
};
let odin_claim = mind_publication(
&odin,
@ -311,6 +326,8 @@ fn three_repo_vertical_slice_wakes_direct_then_transitive_modeling() -> Result<(
failure_semantics: AtlasFailureSemantics::FailClosed,
impact_scope: AtlasImpactScope::WholeRepository,
lifecycle: AtlasClaimLifecycle::Active,
label: "Epiphany consumes Odin catalog".into(),
body_evidence: body_evidence(),
};
let epiphany_claim = mind_publication(
&epiphany,
@ -355,6 +372,13 @@ fn three_repo_vertical_slice_wakes_direct_then_transitive_modeling() -> Result<(
.iter()
.all(|edge| edge.compatibility == AtlasCompatibility::Exact)
);
assert!(projection.entanglements.iter().all(|edge| {
!edge.claim_label.is_empty()
&& !edge.claim_body_evidence.is_empty()
&& edge.offer_label.is_some()
&& edge.offer_contract.is_some()
&& !edge.offer_body_evidence.is_empty()
}));
let eve_radius = projection
.blast_radii
.iter()
@ -752,6 +776,8 @@ fn contracts_are_closed_and_local_authority_is_explicit() -> Result<()> {
schema_id: "schema:api:v1".into(),
},
lifecycle: AtlasOfferLifecycle::Active,
label: "Exact schema API surface".into(),
body_evidence: body_evidence(),
};
assert_eq!(
evaluate_atlas_compatibility(&claim, Some(&offer)),
@ -909,6 +935,14 @@ fn deterministic_join_uses_exact_status_watermarks_and_exact_verification() -> R
first.entanglements[0].verification,
AtlasVerificationState::Passed
);
assert_eq!(
first.entanglements[0].verification_publication_id,
Some(verification.statement.publication_id.clone())
);
assert_eq!(
first.entanglements[0].verification_evidence_sha256,
Some(digest("verified"))
);
assert_eq!(first.source_publication_ids.len(), 5);
assert_eq!(atlas_projection_digest(&first)?, first.projection_sha256);

View file

@ -665,11 +665,146 @@ fn append_modeling_repo_model_shape_snapshot(
item.source_scope.join(" | "),
));
}
context.push_str("RepoModel mutations address semantic document identities directly. New nodes must reference one exact existing domain id or a domain created by the same mutation. Every unresolved frontier item must target at least one exact existing claim id or a claim created by the same mutation. Every frontier source_scope must be non-empty and contain safe relative paths in strict lexicographic ascending order without duplicates. Recommended next organ must use its exact canonical spelling. RepoArchitecture and RepoDataflow nodes/edges may use only observed, proposed, accepted, stale, or retired lifecycle. The projection digest is display and audit identity, never a global stale-write fence.\n");
context.push_str("existingSurfaceOffers:\n");
for offer in &view.surface_offers {
context.push_str(&format!(
"- surfaceId={} label={} contract={} lifecycle={} sourceRefs={}\n",
offer.surface_id,
offer.label,
render_atlas_contract_descriptor(&offer.contract),
render_atlas_offer_lifecycle(&offer.lifecycle),
offer
.body_evidence
.iter()
.map(|source| format!("{}@{}", source.path, source.raw_sha256))
.collect::<Vec<_>>()
.join(" | "),
));
}
context.push_str("existingDependencyClaims:\n");
for claim in &view.dependency_claims {
context.push_str(&format!(
"- claimId={} label={} target={} kind={} failureSemantics={} impactScope={} lifecycle={} sourceRefs={}\n",
claim.claim_id,
claim.label,
render_atlas_dependency_target(&claim.target),
debug_variant_snake_case(claim.entanglement_kind),
debug_variant_snake_case(claim.failure_semantics),
render_atlas_impact_scope(&claim.impact_scope),
debug_variant_snake_case(claim.lifecycle),
claim
.body_evidence
.iter()
.map(|source| format!("{}@{}", source.path, source.raw_sha256))
.collect::<Vec<_>>()
.join(" | "),
));
}
context.push_str("currentDependencyVerifications:\n");
for verification in &view.dependency_verifications {
context.push_str(&format!(
"- claimId={} verdict={} claimPublication={} offerPublication={}\n",
verification.claim_id,
debug_variant_snake_case(verification.verdict),
verification.claim_publication_id,
verification.offer_publication_id,
));
}
context.push_str("currentDependencyImpacts:\n");
for impact in &view.dependency_impacts {
context.push_str(&format!(
"- impactId={} claimId={} criticality={} projection={}\n",
impact.impact_id,
impact.claim_id,
debug_variant_snake_case(impact.criticality),
impact.projection_sha256,
));
}
context.push_str("RepoModel mutations address semantic document identities directly. New nodes must reference one exact existing domain id or a domain created by the same mutation. Every unresolved frontier item must target at least one exact existing claim id or a claim created by the same mutation. Every frontier source_scope must be non-empty and contain safe relative paths in strict lexicographic ascending order without duplicates. Recommended next organ must use its exact canonical spelling. RepoArchitecture and RepoDataflow nodes/edges may use only observed, proposed, accepted, stale, or retired lifecycle. Atlas create operations do not accept caller-authored offer or claim ids: runtime derives opaque UUIDs from the admitted proposal. Lifecycle operations may name only ids listed above. Exact dependency targets must name a provider repository and surface; unresolved targets remain unresolved. Local-surface impact scopes may name only locally owned surface ids listed above. The projection digest is display and audit identity, never a global stale-write fence.\n");
context.push_str("</canonical_repo_model_shape>");
context
}
fn render_atlas_contract_descriptor(contract: &crate::AtlasContractDescriptor) -> String {
match contract {
crate::AtlasContractDescriptor::Semver {
contract_id,
version,
} => format!("semver:{contract_id}@{version}"),
crate::AtlasContractDescriptor::ExactSchema {
contract_id,
schema_id,
} => format!("exact_schema:{contract_id}@{schema_id}"),
crate::AtlasContractDescriptor::ExactDigest {
contract_id,
sha256,
} => format!("exact_digest:{contract_id}@{sha256}"),
}
}
fn render_atlas_contract_requirement(requirement: &crate::AtlasContractRequirement) -> String {
match requirement {
crate::AtlasContractRequirement::Semver {
contract_id,
requirement,
} => format!("semver:{contract_id}@{requirement}"),
crate::AtlasContractRequirement::ExactSchema {
contract_id,
schema_id,
} => format!("exact_schema:{contract_id}@{schema_id}"),
crate::AtlasContractRequirement::ExactDigest {
contract_id,
sha256,
} => format!("exact_digest:{contract_id}@{sha256}"),
}
}
fn render_atlas_offer_lifecycle(lifecycle: &crate::AtlasOfferLifecycle) -> String {
match lifecycle {
crate::AtlasOfferLifecycle::Active => "active".to_string(),
crate::AtlasOfferLifecycle::Deprecated {
replacement_surface_id: Some(replacement_surface_id),
} => format!("deprecated:replacement={replacement_surface_id}"),
crate::AtlasOfferLifecycle::Deprecated {
replacement_surface_id: None,
} => "deprecated".to_string(),
crate::AtlasOfferLifecycle::Withdrawn => "withdrawn".to_string(),
}
}
fn render_atlas_dependency_target(target: &crate::AtlasDependencyTarget) -> String {
match target {
crate::AtlasDependencyTarget::Exact {
provider,
surface_id,
requirement,
} => format!(
"exact:{}#{} requires {}",
provider.repository_uri,
surface_id,
render_atlas_contract_requirement(requirement)
),
crate::AtlasDependencyTarget::Unresolved { requirement } => format!(
"unresolved:{}",
render_atlas_contract_requirement(requirement)
),
}
}
fn render_atlas_impact_scope(scope: &crate::AtlasImpactScope) -> String {
match scope {
crate::AtlasImpactScope::WholeRepository => "whole_repository".to_string(),
crate::AtlasImpactScope::LocalSurfaces { surface_ids } => format!(
"local_surfaces:{}",
surface_ids
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join("|")
),
}
}
fn debug_variant_snake_case(value: impl std::fmt::Debug) -> String {
let name = format!("{value:?}");
let mut output = String::with_capacity(name.len() + 4);

View file

@ -100,7 +100,8 @@ Every upserted or revised node must include all canonical identity and judgment
If you emit an `anchor`, it must include its own stable `id`, `kind`, and `target`; a nested `code_ref` must include `path`. Do not use a bare path-shaped object as an anchor. Omitting anchors is safer than inventing malformed provenance.
The launch context includes `<canonical_repo_model_shape>`. Every new node must use one exact `existingDomains` id from that packet, and repo architecture/dataflow nodes and edges must use one of the listed legal lifecycles. Never derive a domain id from the workspace path.
When `<repo_frontier_modeling_request>` is present, return only `frontierVerdictGap`: the semantic explanation for the allowed resolved or blocked transition. Runtime composes the exact routed frontier mutation and binds the authenticated request, Soul evidence, disposition, and time. Do not echo those identifiers or construct the mutation yourself.
Ordinary Modeling may emit `put_node`, `retire_node`, `put_edge`, or `retire_edge`. `checkpoint-update-needed` additionally requires exactly one `put_frontier`; `checkpoint-ready` and `regather-needed` require an empty operation array. Do not invent frontier authority from prose.
Ordinary Modeling may emit `put_node`, `retire_node`, `put_edge`, `retire_edge`, `create_surface_offer`, `deprecate_surface_offer`, `withdraw_surface_offer`, `create_dependency_claim`, or `retire_dependency_claim`. Atlas create operations require a human-readable label and a non-empty, strictly sorted set of exact repository-relative `source_refs` from the current Body. They otherwise carry semantic contract or dependency content only; runtime resolves the evidence paths to exact Body digests and derives the provider/consumer identity, active lifecycle, causal request/result/evidence bindings, and opaque offer/claim UUID. Lifecycle operations may name only an exact existing Atlas id shown in `<canonical_repo_model_shape>`. Exact claims name the provider repository and surface; unresolved contract claims remain unresolved until a later Modeling turn selects an explicit target. Local-surface impact scope may name only existing locally owned offer ids. Build, deployment, and infrastructure-control claims must use `fail_closed`. Never describe a foreign repository by writing its Mind; publish only this repository's offer or claim.
`checkpoint-update-needed` additionally requires exactly one `put_frontier`. `checkpoint-ready` may carry only the Atlas offer/claim transitions above, or an empty array when no current Body fact changed. `regather-needed` requires an empty operation array. Do not invent frontier authority from prose.
When the typed launch document contains `proposalModelingContext`, emit only `proposalFrontierDraft`. Runtime composes the frontier identity, active lifecycle, Body basis, proposal/request provenance, timestamps, and mandatory evidence binding. Normalize relevant scope hints into safe relative paths in strict lexicographic order without duplicates, and choose `Hands`, `Eyes`, or `Imagination` from the actual unresolved work. The proposal is evidence, not campaign truth: Mind still owns admission, and Hands still owns execution.
Generic `statePatch` is optional and has been stripped of repository-anatomy authority. If present, it may contain only coherent `observations` and `evidence`. Never put graphs, graph frontier, graph checkpoint, scratch, investigation checkpoint, planning, objectives, jobs, or other anatomy in `statePatch`; those old paths are demoted and will be rejected.
Do not edit files, do not implement product code, do not verify as if you were the reviewer, do not change jobs/subgoals/objective/invariants/churn/mode, and do not promote or accept your own output.

View file

@ -122,6 +122,10 @@ pub struct EpiphanyRepoModelView {
pub frontier: Vec<RepoFrontierItem>,
pub lifecycle_receipts: Vec<EpiphanyMemoryLifecycleReceipt>,
pub claim_obligations: Vec<EpiphanyRepoModelClaimObligationsDocument>,
pub surface_offers: Vec<crate::AtlasSurfaceOffer>,
pub dependency_claims: Vec<crate::AtlasDependencyClaim>,
pub dependency_verifications: Vec<crate::AtlasDependencyVerification>,
pub dependency_impacts: Vec<crate::AtlasDependencyImpact>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@ -242,7 +246,7 @@ impl EpiphanyRepoModelBasis {
}
pub const REPO_MODEL_MUTATION_PROPOSAL_SCHEMA_VERSION: &str =
"epiphany.repo_model.mutation_proposal.v1";
"epiphany.repo_model.mutation_proposal.v2";
pub const REPO_MODEL_SEED_SCHEMA_VERSION: &str = "epiphany.repo_model.seed.v1";
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@ -360,18 +364,55 @@ impl EpiphanyRepoModelSeed {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "operation", rename_all = "snake_case")]
pub enum EpiphanyRepoModelMutationOperation {
PutDomain { domain: EpiphanyMemoryDomain },
PutNode { node: EpiphanyMemoryNode },
RetireNode { node_id: String },
PutEdge { edge: EpiphanyMemoryEdge },
RetireEdge { edge_id: String },
PutSummary { summary: EpiphanyMemorySummary },
PutFrontier { item: RepoFrontierItem },
PutDomain {
domain: EpiphanyMemoryDomain,
},
PutNode {
node: EpiphanyMemoryNode,
},
RetireNode {
node_id: String,
},
PutEdge {
edge: EpiphanyMemoryEdge,
},
RetireEdge {
edge_id: String,
},
PutSummary {
summary: EpiphanyMemorySummary,
},
PutFrontier {
item: RepoFrontierItem,
},
CreateSurfaceOffer {
label: String,
contract: crate::AtlasContractDescriptor,
source_refs: Vec<String>,
},
DeprecateSurfaceOffer {
surface_id: uuid::Uuid,
replacement_surface_id: Option<uuid::Uuid>,
},
WithdrawSurfaceOffer {
surface_id: uuid::Uuid,
},
CreateDependencyClaim {
label: String,
target: crate::AtlasDependencyTarget,
entanglement_kind: crate::AtlasEntanglementKind,
failure_semantics: crate::AtlasFailureSemantics,
impact_scope: crate::AtlasImpactScope,
source_refs: Vec<String>,
},
RetireDependencyClaim {
claim_id: uuid::Uuid,
},
}
#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.repo_model.mutation_proposal.v1",
type = "epiphany.repo_model.mutation_proposal.v2",
schema = "EpiphanyRepoModelMutationProposal"
)]
pub struct EpiphanyRepoModelMutationProposal {
@ -380,17 +421,35 @@ pub struct EpiphanyRepoModelMutationProposal {
#[cultcache(key = 1)]
pub proposal_id: String,
#[cultcache(key = 2)]
pub causal_request_id: String,
#[cultcache(key = 3)]
pub causal_result_id: String,
#[cultcache(key = 4)]
pub evidence_ids: Vec<String>,
#[cultcache(key = 5)]
pub repository_body_observation_basis: crate::RepositoryBodyObservationBasis,
#[cultcache(key = 6)]
pub operations_msgpack: Vec<u8>,
}
impl EpiphanyRepoModelMutationProposal {
pub fn new(
proposal_id: impl Into<String>,
causal_request_id: impl Into<String>,
causal_result_id: impl Into<String>,
mut evidence_ids: Vec<String>,
repository_body_observation_basis: crate::RepositoryBodyObservationBasis,
operations: Vec<EpiphanyRepoModelMutationOperation>,
) -> Result<Self> {
evidence_ids.sort();
evidence_ids.dedup();
let proposal = Self {
schema_version: REPO_MODEL_MUTATION_PROPOSAL_SCHEMA_VERSION.into(),
proposal_id: proposal_id.into(),
causal_request_id: causal_request_id.into(),
causal_result_id: causal_result_id.into(),
evidence_ids,
repository_body_observation_basis,
operations_msgpack: rmp_serde::to_vec_named(&operations)?,
};
proposal.validate()?;
@ -405,6 +464,14 @@ impl EpiphanyRepoModelMutationProposal {
pub fn validate(&self) -> Result<()> {
if self.schema_version != REPO_MODEL_MUTATION_PROPOSAL_SCHEMA_VERSION
|| self.proposal_id.trim().is_empty()
|| self.causal_request_id.trim().is_empty()
|| self.causal_result_id.trim().is_empty()
|| self.evidence_ids.is_empty()
|| self
.evidence_ids
.iter()
.any(|value| value.trim().is_empty())
|| !self.evidence_ids.windows(2).all(|pair| pair[0] < pair[1])
|| self.operations()?.is_empty()
{
return Err(anyhow!("RepoModel mutation proposal is empty"));
@ -628,6 +695,22 @@ pub(crate) fn repo_model_write_key(envelope: &CultCacheEnvelope) -> Result<Optio
return Err(anyhow!("RepoModel claim obligations are not canonical"));
}
value.node_id
} else if envelope.r#type == crate::AtlasSurfaceOffer::TYPE {
let value: crate::AtlasSurfaceOffer = rmp_serde::from_slice(&envelope.payload)?;
value.validate()?;
value.surface_id.to_string()
} else if envelope.r#type == crate::AtlasDependencyClaim::TYPE {
let value: crate::AtlasDependencyClaim = rmp_serde::from_slice(&envelope.payload)?;
value.validate()?;
value.claim_id.to_string()
} else if envelope.r#type == crate::AtlasDependencyVerification::TYPE {
let value: crate::AtlasDependencyVerification = rmp_serde::from_slice(&envelope.payload)?;
value.validate()?;
value.claim_id.to_string()
} else if envelope.r#type == crate::AtlasDependencyImpact::TYPE {
let value: crate::AtlasDependencyImpact = rmp_serde::from_slice(&envelope.payload)?;
value.validate()?;
value.impact_id.to_string()
} else {
return Ok(None);
};
@ -642,10 +725,41 @@ pub fn plan_repo_model_mutation(
proposal: &EpiphanyRepoModelMutationProposal,
) -> Result<EpiphanyRepoModelMutationPlan> {
proposal.validate()?;
crate::validate_repository_body_observation_basis(
store_path.as_ref(),
&proposal.repository_body_observation_basis,
)?;
if crate::load_current_runtime_repository_body_basis(store_path.as_ref())?
!= proposal.repository_body_observation_basis
{
return Err(anyhow!(
"RepoModel mutation proposal lost its exact current Repository Body basis"
));
}
let operations = proposal.operations()?;
let mut cache = runtime_spine_cache(store_path.as_ref())?;
cache.pull_all_backing_stores()?;
let view = assemble_repo_model_view(store_path.as_ref())?;
let local_repository = crate::AtlasRepositoryIdentity::new(
view.identity.swarm_id.clone(),
view.identity.workspace_id.clone(),
)?;
if proposal.repository_body_observation_basis.swarm_id != view.identity.swarm_id
|| proposal.repository_body_observation_basis.workspace_id != view.identity.workspace_id
|| proposal.repository_body_observation_basis.runtime_id != view.identity.runtime_id
|| proposal
.repository_body_observation_basis
.body_binding_sha256
!= view.identity.body_binding_sha256
{
return Err(anyhow!(
"RepoModel mutation proposal Body basis disagrees with the keyed model identity"
));
}
let body_manifest = crate::authenticated_repository_body_manifest(
store_path.as_ref(),
&proposal.repository_body_observation_basis,
)?;
let identity_envelope = cache
.get_envelope::<EpiphanyRepoModelIdentityDocument>(REPO_MODEL_IDENTITY_KEY)?
.ok_or_else(|| anyhow!("RepoModel mutation lost its identity envelope"))?;
@ -717,7 +831,15 @@ pub fn plan_repo_model_mutation(
.collect::<BTreeSet<_>>();
let operation_identities = operations
.iter()
.map(repo_model_operation_identity)
.enumerate()
.map(|(index, operation)| {
repo_model_operation_identity(
&proposal.proposal_id,
index,
&local_repository,
operation,
)
})
.collect::<Result<BTreeSet<_>>>()?;
if operation_identities.len() != operations.len() {
return Err(anyhow!(
@ -733,7 +855,7 @@ pub fn plan_repo_model_mutation(
identity_envelope,
)]);
let mut writes = BTreeMap::new();
for operation in &operations {
for (operation_index, operation) in operations.iter().enumerate() {
match operation {
EpiphanyRepoModelMutationOperation::PutDomain { domain } => {
require_semantic_id(&domain.id, "RepoModel domain")?;
@ -958,6 +1080,150 @@ pub fn plan_repo_model_mutation(
.0,
)?;
}
EpiphanyRepoModelMutationOperation::CreateSurfaceOffer {
label,
contract,
source_refs,
} => {
contract.validate()?;
let body_evidence = resolve_atlas_body_evidence(&body_manifest, source_refs)?;
let surface_id = derived_atlas_operation_id(
&proposal.proposal_id,
operation_index,
&local_repository,
"surface-offer",
);
let offer = crate::AtlasSurfaceOffer {
schema_version: crate::ATLAS_SURFACE_OFFER_SCHEMA.into(),
provider: local_repository.clone(),
surface_id,
contract: contract.clone(),
lifecycle: crate::AtlasOfferLifecycle::Active,
label: label.clone(),
body_evidence,
};
offer.validate()?;
if let Some(existing) =
cache.get_envelope::<crate::AtlasSurfaceOffer>(&surface_id.to_string())?
{
insert_strong_envelope(&mut strong, existing)?;
}
insert_envelope(
&mut writes,
cache.prepare_entry(&surface_id.to_string(), &offer)?.0,
)?;
}
EpiphanyRepoModelMutationOperation::DeprecateSurfaceOffer {
surface_id,
replacement_surface_id,
} => {
let (mut offer, current_envelope) =
load_local_surface_offer(&cache, &local_repository, *surface_id)?;
if offer.lifecycle != crate::AtlasOfferLifecycle::Active {
return Err(anyhow!(
"Atlas offer deprecation requires an active local surface"
));
}
insert_strong_envelope(&mut strong, current_envelope)?;
if let Some(replacement_id) = replacement_surface_id {
let (replacement, replacement_envelope) =
load_local_surface_offer(&cache, &local_repository, *replacement_id)?;
if replacement.surface_id == offer.surface_id
|| replacement.lifecycle != crate::AtlasOfferLifecycle::Active
|| replacement.contract.contract_id() != offer.contract.contract_id()
{
return Err(anyhow!(
"Atlas replacement surface is recursive, inactive, or contract-ambiguous"
));
}
insert_strong_envelope(&mut strong, replacement_envelope)?;
}
offer.lifecycle = crate::AtlasOfferLifecycle::Deprecated {
replacement_surface_id: *replacement_surface_id,
};
offer.validate()?;
insert_envelope(
&mut writes,
cache.prepare_entry(&surface_id.to_string(), &offer)?.0,
)?;
}
EpiphanyRepoModelMutationOperation::WithdrawSurfaceOffer { surface_id } => {
let (mut offer, current_envelope) =
load_local_surface_offer(&cache, &local_repository, *surface_id)?;
if !matches!(
offer.lifecycle,
crate::AtlasOfferLifecycle::Active
| crate::AtlasOfferLifecycle::Deprecated { .. }
) {
return Err(anyhow!(
"Atlas offer withdrawal requires an active or deprecated local surface"
));
}
insert_strong_envelope(&mut strong, current_envelope)?;
offer.lifecycle = crate::AtlasOfferLifecycle::Withdrawn;
offer.validate()?;
insert_envelope(
&mut writes,
cache.prepare_entry(&surface_id.to_string(), &offer)?.0,
)?;
}
EpiphanyRepoModelMutationOperation::CreateDependencyClaim {
label,
target,
entanglement_kind,
failure_semantics,
impact_scope,
source_refs,
} => {
target.validate()?;
impact_scope.validate()?;
let body_evidence = resolve_atlas_body_evidence(&body_manifest, source_refs)?;
require_local_impact_scope(&cache, &local_repository, impact_scope, &mut strong)?;
let claim_id = derived_atlas_operation_id(
&proposal.proposal_id,
operation_index,
&local_repository,
"dependency-claim",
);
let claim = crate::AtlasDependencyClaim {
schema_version: crate::ATLAS_DEPENDENCY_CLAIM_SCHEMA.into(),
consumer: local_repository.clone(),
claim_id,
target: target.clone(),
entanglement_kind: *entanglement_kind,
failure_semantics: *failure_semantics,
impact_scope: impact_scope.clone(),
lifecycle: crate::AtlasClaimLifecycle::Active,
label: label.clone(),
body_evidence,
};
claim.validate()?;
if let Some(existing) =
cache.get_envelope::<crate::AtlasDependencyClaim>(&claim_id.to_string())?
{
insert_strong_envelope(&mut strong, existing)?;
}
insert_envelope(
&mut writes,
cache.prepare_entry(&claim_id.to_string(), &claim)?.0,
)?;
}
EpiphanyRepoModelMutationOperation::RetireDependencyClaim { claim_id } => {
let (mut claim, current_envelope) =
load_local_dependency_claim(&cache, &local_repository, *claim_id)?;
if claim.lifecycle != crate::AtlasClaimLifecycle::Active {
return Err(anyhow!(
"Atlas claim retirement requires an active local claim"
));
}
insert_strong_envelope(&mut strong, current_envelope)?;
claim.lifecycle = crate::AtlasClaimLifecycle::Retired;
claim.validate()?;
insert_envelope(
&mut writes,
cache.prepare_entry(&claim_id.to_string(), &claim)?.0,
)?;
}
}
}
@ -979,19 +1245,159 @@ pub fn plan_repo_model_mutation(
}
fn repo_model_operation_identity(
proposal_id: &str,
operation_index: usize,
local_repository: &crate::AtlasRepositoryIdentity,
operation: &EpiphanyRepoModelMutationOperation,
) -> Result<(String, String)> {
let (kind, id) = match operation {
EpiphanyRepoModelMutationOperation::PutDomain { domain } => ("domain", &domain.id),
EpiphanyRepoModelMutationOperation::PutNode { node } => ("node", &node.id),
EpiphanyRepoModelMutationOperation::RetireNode { node_id } => ("node", node_id),
EpiphanyRepoModelMutationOperation::PutEdge { edge } => ("edge", &edge.id),
EpiphanyRepoModelMutationOperation::RetireEdge { edge_id } => ("edge", edge_id),
EpiphanyRepoModelMutationOperation::PutSummary { summary } => ("summary", &summary.id),
EpiphanyRepoModelMutationOperation::PutFrontier { item } => ("frontier", &item.id),
EpiphanyRepoModelMutationOperation::PutDomain { domain } => ("domain", domain.id.clone()),
EpiphanyRepoModelMutationOperation::PutNode { node } => ("node", node.id.clone()),
EpiphanyRepoModelMutationOperation::RetireNode { node_id } => ("node", node_id.clone()),
EpiphanyRepoModelMutationOperation::PutEdge { edge } => ("edge", edge.id.clone()),
EpiphanyRepoModelMutationOperation::RetireEdge { edge_id } => ("edge", edge_id.clone()),
EpiphanyRepoModelMutationOperation::PutSummary { summary } => {
("summary", summary.id.clone())
}
EpiphanyRepoModelMutationOperation::PutFrontier { item } => ("frontier", item.id.clone()),
EpiphanyRepoModelMutationOperation::CreateSurfaceOffer { .. } => (
"surface_offer",
derived_atlas_operation_id(
proposal_id,
operation_index,
local_repository,
"surface-offer",
)
.to_string(),
),
EpiphanyRepoModelMutationOperation::DeprecateSurfaceOffer { surface_id, .. }
| EpiphanyRepoModelMutationOperation::WithdrawSurfaceOffer { surface_id } => {
("surface_offer", surface_id.to_string())
}
EpiphanyRepoModelMutationOperation::CreateDependencyClaim { .. } => (
"dependency_claim",
derived_atlas_operation_id(
proposal_id,
operation_index,
local_repository,
"dependency-claim",
)
.to_string(),
),
EpiphanyRepoModelMutationOperation::RetireDependencyClaim { claim_id } => {
("dependency_claim", claim_id.to_string())
}
};
require_semantic_id(id, "RepoModel operation")?;
Ok((kind.into(), id.clone()))
require_semantic_id(&id, "RepoModel operation")?;
Ok((kind.into(), id))
}
fn derived_atlas_operation_id(
proposal_id: &str,
operation_index: usize,
local_repository: &crate::AtlasRepositoryIdentity,
kind: &str,
) -> uuid::Uuid {
let name = format!(
"{}/epiphany/modeling/{proposal_id}/{kind}/{operation_index}",
local_repository.repository_uri
);
uuid::Uuid::new_v5(&uuid::Uuid::NAMESPACE_URL, name.as_bytes())
}
fn load_local_surface_offer(
cache: &CultCache,
local_repository: &crate::AtlasRepositoryIdentity,
surface_id: uuid::Uuid,
) -> Result<(crate::AtlasSurfaceOffer, CultCacheEnvelope)> {
if surface_id.is_nil() {
return Err(anyhow!("Atlas surface transition requires a non-nil UUID"));
}
let key = surface_id.to_string();
let envelope = cache
.get_envelope::<crate::AtlasSurfaceOffer>(&key)?
.ok_or_else(|| anyhow!("Atlas surface transition targets a missing local offer"))?;
let offer: crate::AtlasSurfaceOffer = rmp_serde::from_slice(&envelope.payload)?;
offer.validate()?;
if offer.provider != *local_repository || offer.surface_id != surface_id {
return Err(anyhow!(
"Atlas surface transition cannot write a foreign or substituted offer"
));
}
Ok((offer, envelope))
}
fn load_local_dependency_claim(
cache: &CultCache,
local_repository: &crate::AtlasRepositoryIdentity,
claim_id: uuid::Uuid,
) -> Result<(crate::AtlasDependencyClaim, CultCacheEnvelope)> {
if claim_id.is_nil() {
return Err(anyhow!("Atlas claim transition requires a non-nil UUID"));
}
let key = claim_id.to_string();
let envelope = cache
.get_envelope::<crate::AtlasDependencyClaim>(&key)?
.ok_or_else(|| anyhow!("Atlas claim transition targets a missing local claim"))?;
let claim: crate::AtlasDependencyClaim = rmp_serde::from_slice(&envelope.payload)?;
claim.validate()?;
if claim.consumer != *local_repository || claim.claim_id != claim_id {
return Err(anyhow!(
"Atlas claim transition cannot write a foreign or substituted claim"
));
}
Ok((claim, envelope))
}
fn require_local_impact_scope(
cache: &CultCache,
local_repository: &crate::AtlasRepositoryIdentity,
impact_scope: &crate::AtlasImpactScope,
strong: &mut BTreeMap<(String, String), CultCacheEnvelope>,
) -> Result<()> {
let crate::AtlasImpactScope::LocalSurfaces { surface_ids } = impact_scope else {
return Ok(());
};
for surface_id in surface_ids {
let (_, envelope) = load_local_surface_offer(cache, local_repository, *surface_id)?;
insert_strong_envelope(strong, envelope)?;
}
Ok(())
}
fn resolve_atlas_body_evidence(
manifest: &crate::RepositoryBodyManifest,
source_refs: &[String],
) -> Result<Vec<crate::AtlasBodyEvidenceRef>> {
if source_refs.is_empty() || !source_refs.windows(2).all(|pair| pair[0] < pair[1]) {
return Err(anyhow!(
"Atlas offer and claim source refs must be a non-empty strictly sorted set"
));
}
let entries = manifest
.entries
.iter()
.map(|entry| (entry.path.as_str(), entry))
.collect::<BTreeMap<_, _>>();
source_refs
.iter()
.map(|path| {
let entry = entries.get(path.as_str()).ok_or_else(|| {
anyhow!("Atlas source ref {path:?} is absent from the exact Body manifest")
})?;
if entry.kind != "regular" {
return Err(anyhow!(
"Atlas source ref {path:?} is not a regular repository Body file"
));
}
let evidence = crate::AtlasBodyEvidenceRef {
path: path.clone(),
raw_sha256: entry.raw_sha256.clone(),
};
evidence.validate()?;
Ok(evidence)
})
.collect()
}
fn insert_envelope(
@ -1096,6 +1502,10 @@ pub(crate) fn assemble_repo_model_view_from_cache(
let mut lifecycle_receipts =
values::<EpiphanyRepoModelLifecycleReceiptDocument, _>(&cache, |entry| entry.value())?;
let mut claim_obligations = cache.get_all::<EpiphanyRepoModelClaimObligationsDocument>()?;
let mut surface_offers = cache.get_all::<crate::AtlasSurfaceOffer>()?;
let mut dependency_claims = cache.get_all::<crate::AtlasDependencyClaim>()?;
let mut dependency_verifications = cache.get_all::<crate::AtlasDependencyVerification>()?;
let mut dependency_impacts = cache.get_all::<crate::AtlasDependencyImpact>()?;
domains.sort_by(|left, right| left.id.cmp(&right.id));
nodes.sort_by(|left, right| left.id.cmp(&right.id));
edges.sort_by(|left, right| left.id.cmp(&right.id));
@ -1103,6 +1513,32 @@ pub(crate) fn assemble_repo_model_view_from_cache(
frontier.sort_by(|left, right| left.id.cmp(&right.id));
lifecycle_receipts.sort_by(|left, right| left.id.cmp(&right.id));
claim_obligations.sort_by(|left, right| left.node_id.cmp(&right.node_id));
surface_offers.sort_by_key(|offer| offer.surface_id);
dependency_claims.sort_by_key(|claim| claim.claim_id);
dependency_verifications.sort_by_key(|verification| verification.claim_id);
dependency_impacts.sort_by_key(|impact| impact.impact_id);
let local_repository = crate::AtlasRepositoryIdentity::new(
identity.swarm_id.clone(),
identity.workspace_id.clone(),
)?;
if surface_offers
.iter()
.any(|offer| offer.provider != local_repository || offer.validate().is_err())
|| dependency_claims
.iter()
.any(|claim| claim.consumer != local_repository || claim.validate().is_err())
|| dependency_verifications.iter().any(|verification| {
verification.consumer != local_repository || verification.validate().is_err()
})
|| dependency_impacts
.iter()
.any(|impact| impact.consumer != local_repository || impact.validate().is_err())
{
return Err(anyhow!(
"keyed RepoModel view contains a foreign or invalid local Atlas document"
));
}
validate_repo_model_parts(
&identity,
@ -1118,7 +1554,7 @@ pub(crate) fn assemble_repo_model_view_from_cache(
let mut source_documents = cache
.snapshot_envelopes()
.into_iter()
.filter(|entry| entry.r#type.starts_with("epiphany.mind.repo_model."))
.filter(|entry| repo_model_write_key(entry).is_ok_and(|key| key.is_some()))
.map(|entry| EpiphanyMindDocumentVersion::from_envelope("epiphany-mind", &entry))
.collect::<Result<Vec<_>>>()?;
source_documents.sort_by(|left, right| {
@ -1139,6 +1575,10 @@ pub(crate) fn assemble_repo_model_view_from_cache(
frontier,
lifecycle_receipts,
claim_obligations,
surface_offers,
dependency_claims,
dependency_verifications,
dependency_impacts,
})
}
@ -1239,6 +1679,31 @@ mod tests {
EpiphanyMemoryProfile, RepoFrontierStatus,
};
fn bind_test_body(
store: &Path,
swarm_id: &str,
workspace_id: &str,
) -> Result<crate::RepositoryBodyObservationBasis> {
crate::runtime_spine::tests::bind_test_runtime_swarm(store, swarm_id)?;
crate::runtime_spine::tests::bind_test_repository_body(store, workspace_id)?;
crate::observe_runtime_repository_body_basis(store)
}
fn make_proposal(
proposal_id: &str,
body: &crate::RepositoryBodyObservationBasis,
operations: Vec<EpiphanyRepoModelMutationOperation>,
) -> Result<EpiphanyRepoModelMutationProposal> {
EpiphanyRepoModelMutationProposal::new(
proposal_id,
format!("request-{proposal_id}"),
format!("result-{proposal_id}"),
vec![format!("evidence-{proposal_id}")],
body.clone(),
operations,
)
}
#[test]
fn fresh_repo_model_seed_commits_keyed_documents_and_refuses_divergent_replay() -> Result<()> {
let temp = tempfile::tempdir()?;
@ -1350,6 +1815,7 @@ mod tests {
created_at: "2026-08-14T00:00:00Z".into(),
},
)?;
let body = bind_test_body(&store, "swarm-1", "workspace-1")?;
let mut cache = runtime_spine_cache(&store)?;
cache.put(
REPO_MODEL_IDENTITY_KEY,
@ -1359,7 +1825,7 @@ mod tests {
runtime_id: "repo-model-view".into(),
swarm_id: "swarm-1".into(),
workspace_id: "workspace-1".into(),
body_binding_sha256: "sha256:body".into(),
body_binding_sha256: body.body_binding_sha256.clone(),
},
)?;
cache.put(
@ -1396,15 +1862,17 @@ mod tests {
let mind = crate::assemble_mind_view(&store)?;
assert_eq!(mind.repo_model.as_ref(), Some(&first));
let retire = EpiphanyRepoModelMutationProposal::new(
let retire = make_proposal(
"proposal-retire",
&body,
vec![EpiphanyRepoModelMutationOperation::RetireNode {
node_id: "node-1".into(),
}],
)?;
let retire_plan = plan_repo_model_mutation(&store, &retire)?;
let add_frontier = EpiphanyRepoModelMutationProposal::new(
let add_frontier = make_proposal(
"proposal-frontier",
&body,
vec![EpiphanyRepoModelMutationOperation::PutFrontier {
item: RepoFrontierItem {
id: "frontier-1".into(),
@ -1466,6 +1934,7 @@ mod tests {
created_at: "2026-08-14T00:00:00Z".into(),
},
)?;
let body = bind_test_body(&store, "swarm-1", "workspace-1")?;
let mut cache = runtime_spine_cache(&store)?;
cache.put(
REPO_MODEL_IDENTITY_KEY,
@ -1475,7 +1944,7 @@ mod tests {
runtime_id: "repo-model-atomic-slice".into(),
swarm_id: "swarm-1".into(),
workspace_id: "workspace-1".into(),
body_binding_sha256: "sha256:body".into(),
body_binding_sha256: body.body_binding_sha256.clone(),
},
)?;
let domain = EpiphanyMemoryDomain {
@ -1521,8 +1990,9 @@ mod tests {
action_implication: "Commit the exact keyed slice".into(),
..Default::default()
};
let proposal = EpiphanyRepoModelMutationProposal::new(
let proposal = make_proposal(
"proposal-atomic-slice",
&body,
vec![
EpiphanyRepoModelMutationOperation::PutSummary {
summary: summary.clone(),
@ -1556,8 +2026,9 @@ mod tests {
assert_eq!(view.edges, [edge.clone()]);
assert_eq!(view.summaries, [summary]);
let retire = EpiphanyRepoModelMutationProposal::new(
let retire = make_proposal(
"proposal-retire-edge",
&body,
vec![EpiphanyRepoModelMutationOperation::RetireEdge {
edge_id: "edge-flow".into(),
}],
@ -1580,8 +2051,9 @@ mod tests {
EpiphanyMemoryLifecycle::Retired
);
let duplicate = EpiphanyRepoModelMutationProposal::new(
let duplicate = make_proposal(
"proposal-duplicate-edge",
&body,
vec![
EpiphanyRepoModelMutationOperation::PutEdge { edge },
EpiphanyRepoModelMutationOperation::RetireEdge {
@ -1592,4 +2064,186 @@ mod tests {
assert!(plan_repo_model_mutation(&store, &duplicate).is_err());
Ok(())
}
#[test]
fn modeling_operations_own_local_atlas_offer_and_claim_lifecycles() -> Result<()> {
let temp = tempfile::tempdir()?;
let store = temp.path().join("repo-model-atlas.cc");
initialize_runtime_spine(
&store,
RuntimeSpineInitOptions {
runtime_id: "repo-model-atlas".into(),
display_name: "RepoModel Atlas".into(),
created_at: "2026-08-14T00:00:00Z".into(),
},
)?;
let body = bind_test_body(&store, "gamecult-local", "odin")?;
let mut cache = runtime_spine_cache(&store)?;
cache.put(
REPO_MODEL_IDENTITY_KEY,
&EpiphanyRepoModelIdentityDocument {
schema_epoch: REPO_MODEL_SCHEMA_EPOCH.into(),
graph_id: "graph-atlas".into(),
runtime_id: "repo-model-atlas".into(),
swarm_id: "gamecult-local".into(),
workspace_id: "odin".into(),
body_binding_sha256: body.body_binding_sha256.clone(),
},
)?;
let offer_proposal = make_proposal(
"modeling-job-create-offer",
&body,
vec![EpiphanyRepoModelMutationOperation::CreateSurfaceOffer {
label: "Odin provider catalog".into(),
contract: crate::AtlasContractDescriptor::ExactSchema {
contract_id: "odin-provider-catalog".into(),
schema_id: "cultmesh://odin/rendezvous/provider-catalog".into(),
},
source_refs: vec!["body-seed.txt".into()],
}],
)?;
let offer_plan = plan_repo_model_mutation(&store, &offer_proposal)?;
let offer_provenance = cache
.prepare_entry(&offer_proposal.proposal_id, &offer_proposal)?
.0;
assert!(matches!(
crate::commit_operator_mind_mutation(
&store,
offer_provenance,
"Modeling.repo_model_mutation",
offer_plan.strong_reads,
offer_plan.writes,
"2026-08-14T00:00:01Z",
)?,
crate::EpiphanyMindCommitOutcome::Committed(_)
));
let offer_view = assemble_repo_model_view(&store)?;
let offer_id = offer_view.surface_offers[0].surface_id;
assert_eq!(offer_view.surface_offers[0].provider.workspace_id, "odin");
let manifest = crate::authenticated_repository_body_manifest(&store, &body)?;
assert_eq!(
offer_view.surface_offers[0].body_evidence,
[crate::AtlasBodyEvidenceRef {
path: manifest.entries[0].path.clone(),
raw_sha256: manifest.entries[0].raw_sha256.clone(),
}]
);
assert!(offer_view.source_documents.iter().any(|source| {
source.document_type == crate::AtlasSurfaceOffer::TYPE
&& source.document_key == offer_id.to_string()
}));
offer_view.reasoning_basis().validate_current(&store)?;
let eve = crate::AtlasRepositoryIdentity::new("gamecult-local", "eve")?;
let eve_surface = uuid::Uuid::new_v4();
let claim_proposal = make_proposal(
"modeling-job-create-claim",
&body,
vec![EpiphanyRepoModelMutationOperation::CreateDependencyClaim {
label: "Odin consumes Eve surfaces".into(),
target: crate::AtlasDependencyTarget::Exact {
provider: eve,
surface_id: eve_surface,
requirement: crate::AtlasContractRequirement::ExactSchema {
contract_id: "eve-surface".into(),
schema_id: "gamecult.eve.surface.v1".into(),
},
},
entanglement_kind: crate::AtlasEntanglementKind::SchemaProtocol,
failure_semantics: crate::AtlasFailureSemantics::FailClosed,
impact_scope: crate::AtlasImpactScope::LocalSurfaces {
surface_ids: vec![offer_id],
},
source_refs: vec!["body-seed.txt".into()],
}],
)?;
let claim_plan = plan_repo_model_mutation(&store, &claim_proposal)?;
let stale_claim_plan = claim_plan.clone();
let claim_provenance = cache
.prepare_entry(&claim_proposal.proposal_id, &claim_proposal)?
.0;
assert!(matches!(
crate::commit_operator_mind_mutation(
&store,
claim_provenance,
"Modeling.repo_model_mutation",
claim_plan.strong_reads,
claim_plan.writes,
"2026-08-14T00:00:02Z",
)?,
crate::EpiphanyMindCommitOutcome::Committed(_)
));
let claim_id = assemble_repo_model_view(&store)?.dependency_claims[0].claim_id;
let withdraw = make_proposal(
"modeling-job-withdraw-offer",
&body,
vec![EpiphanyRepoModelMutationOperation::WithdrawSurfaceOffer {
surface_id: offer_id,
}],
)?;
let withdraw_plan = plan_repo_model_mutation(&store, &withdraw)?;
let withdraw_provenance = cache.prepare_entry(&withdraw.proposal_id, &withdraw)?.0;
assert!(matches!(
crate::commit_operator_mind_mutation(
&store,
withdraw_provenance,
"Modeling.repo_model_mutation",
withdraw_plan.strong_reads,
withdraw_plan.writes,
"2026-08-14T00:00:03Z",
)?,
crate::EpiphanyMindCommitOutcome::Committed(_)
));
let stale_provenance = cache
.prepare_entry("modeling-job-stale-claim", &claim_proposal)?
.0;
assert!(matches!(
crate::commit_operator_mind_mutation(
&store,
stale_provenance,
"Modeling.repo_model_mutation",
stale_claim_plan.strong_reads,
stale_claim_plan.writes,
"2026-08-14T00:00:04Z",
)?,
crate::EpiphanyMindCommitOutcome::Conflict { .. }
));
let retire = make_proposal(
"modeling-job-retire-claim",
&body,
vec![EpiphanyRepoModelMutationOperation::RetireDependencyClaim { claim_id }],
)?;
let retire_plan = plan_repo_model_mutation(&store, &retire)?;
let retire_provenance = cache.prepare_entry(&retire.proposal_id, &retire)?.0;
assert!(matches!(
crate::commit_operator_mind_mutation(
&store,
retire_provenance,
"Modeling.repo_model_mutation",
retire_plan.strong_reads,
retire_plan.writes,
"2026-08-14T00:00:05Z",
)?,
crate::EpiphanyMindCommitOutcome::Committed(_)
));
let final_view = assemble_repo_model_view(&store)?;
assert_eq!(
final_view.surface_offers[0].lifecycle,
crate::AtlasOfferLifecycle::Withdrawn
);
assert_eq!(
final_view.dependency_claims[0].lifecycle,
crate::AtlasClaimLifecycle::Retired
);
std::fs::write(
store.with_extension("odin.body-repo").join("body-seed.txt"),
b"changed Atlas evidence",
)?;
crate::observe_runtime_repository_body_basis(&store)?;
assert!(plan_repo_model_mutation(&store, &offer_proposal).is_err());
Ok(())
}
}

View file

@ -1008,6 +1008,10 @@ mod tests {
frontier: Vec::new(),
lifecycle_receipts: Vec::new(),
claim_obligations: Vec::new(),
surface_offers: Vec::new(),
dependency_claims: Vec::new(),
dependency_verifications: Vec::new(),
dependency_impacts: Vec::new(),
},
))
}

View file

@ -7494,6 +7494,13 @@ fn commit_repo_frontier_plan_decision_inner(
});
let proposal = crate::EpiphanyRepoModelMutationProposal::new(
format!("repo-frontier-plan-adoption-{decision_id}"),
mind_request.request_id.clone(),
decision_id.clone(),
vec![
candidate.candidate_id.clone(),
mind_request.imagination_result_id.clone(),
],
crate::load_current_runtime_repository_body_basis(runtime_store)?,
vec![crate::EpiphanyRepoModelMutationOperation::PutFrontier { item }],
)?;
let plan = crate::plan_repo_model_mutation(runtime_store, &proposal)?;
@ -9154,6 +9161,10 @@ pub fn relinquish_repo_frontier_hands_route(
item.retired_at = Some(relinquished_at.clone());
let proposal = crate::EpiphanyRepoModelMutationProposal::new(
format!("repo-frontier-relinquishment-{refusal_receipt_id}"),
route.route_id.clone(),
refusal_receipt_id.to_string(),
vec![authority.authority_id.clone(), intent_id.to_string()],
crate::load_current_runtime_repository_body_basis(store_path)?,
vec![crate::EpiphanyRepoModelMutationOperation::PutFrontier { item }],
)?;
let plan = crate::plan_repo_model_mutation(store_path, &proposal)?;
@ -9301,6 +9312,13 @@ pub fn amend_repo_frontier_execution(
"repo-frontier-execution-amendment-{}",
amendment.amendment_id
),
amendment.command_id.clone(),
amendment.amendment_id.clone(),
vec![
amendment.admission_id.clone(),
amendment.packet_sha256.clone(),
],
crate::load_current_runtime_repository_body_basis(store_path)?,
vec![crate::EpiphanyRepoModelMutationOperation::PutFrontier { item }],
)?;
let mutation = crate::plan_repo_model_mutation(store_path, &proposal)?;

View file

@ -1597,7 +1597,7 @@ fn worker_output_contract_text(
"Required proposal-Modeling fields: roleId=modeling, verdict, summary, nextSafeMove, filesInspected, frontierNodeIds, evidenceIds, proposalFrontierDraft. Emit only the semantic frontier draft. Runtime owns and composes proposal identity, Body observation basis, proposal/request provenance, active status, timestamps, and the mandatory proposal evidence binding. Do not emit repoModelOperations, proposalModelingRequestId, repositoryBodyObservationBasis, statePatch, selfPatch, commands, release, or deployment cargo."
}
EpiphanyWorkerLaunchDocument::Role(_) => {
"Required role-result fields: roleId, verdict, summary, nextSafeMove, filesInspected. Modeling workers emit repoModelOperations, an array of semantic keyed operations; use an empty array when no RepoModel mutation is proposed. Never emit proposal ids, model revisions or hashes, timestamps, strong reads, writes, or receipts. Ordinary Imagination workers must include statePatch. Modeling statePatch is optional observations/evidence only. For ordinary Modeling, checkpoint-update-needed is a typed claim that the Body map contains a future design gap: encode exactly one PutFrontier operation with a new active, unadopted frontier, recommended_next_organ=Imagination, empty dependency_item_ids, safe non-empty source_scope, and evidence_refs grounded in top-level evidenceIds. Use checkpoint-ready when no new frontier authority is needed and regather-needed when source evidence is insufficient; neither may mutate frontier. nextSafeMove is display-only and never routes an organ. Use arrays for frontierNodeIds, evidenceIds, openQuestions, evidenceGaps, risks, and artifactRefs when present."
"Required role-result fields: roleId, verdict, summary, nextSafeMove, filesInspected. Modeling workers emit repoModelOperations, an array of semantic keyed operations; use an empty array when no RepoModel mutation is proposed. Never emit proposal ids, model revisions or hashes, timestamps, strong reads, writes, or receipts. Ordinary Imagination workers must include statePatch. Modeling statePatch is optional observations/evidence only. For ordinary Modeling, checkpoint-update-needed is a typed claim that the Body map contains a future design gap: encode exactly one PutFrontier operation with a new active, unadopted frontier, recommended_next_organ=Imagination, empty dependency_item_ids, safe non-empty source_scope, and evidence_refs grounded in top-level evidenceIds. checkpoint-ready may carry only local Atlas offer/claim transitions or an empty operation array; regather-needed requires an empty operation array. Neither may mutate frontier. nextSafeMove is display-only and never routes an organ. Use arrays for frontierNodeIds, evidenceIds, openQuestions, evidenceGaps, risks, and artifactRefs when present."
}
EpiphanyWorkerLaunchDocument::Reorient(_) => {
"Required reorient-result fields: mode, summary, nextSafeMove. Include checkpointStillValid, filesInspected, frontierNodeIds, evidenceIds, openQuestions, and continuityRisks when present."
@ -1794,115 +1794,149 @@ fn role_worker_result_from_ingress(
runtime_evidence_ids: Vec<String>,
artifact_refs: Vec<String>,
) -> EpiphanyRuntimeRoleWorkerResult {
let accepted_evidence_ids = {
let mut evidence_ids = clean_string_vec(&result.evidence_ids);
evidence_ids.extend(clean_string_vec(&runtime_evidence_ids));
if let Some(context) = proposal_modeling_context {
evidence_ids.push(context.proposal_id.clone());
}
evidence_ids.sort();
evidence_ids.dedup();
evidence_ids
};
let repo_model_proposal = |operations| {
let body_basis = repository_body_observation_basis.cloned().ok_or_else(|| {
anyhow!("repoModelOperations: Modeling launch has no current Body basis")
})?;
epiphany_core::EpiphanyRepoModelMutationProposal::new(
format!("repo-model-mutation-proposal-{}", launch_request.job_id),
launch_request.job_id.clone(),
result_id.to_string(),
accepted_evidence_ids.clone(),
body_basis,
operations,
)
};
let (state_patch_msgpack, state_patch_error) =
encode_optional_document(&result.state_patch, "statePatch");
let (repo_model_mutation_proposal_msgpack, repo_model_mutation_proposal_error) =
if let Some(context) = proposal_modeling_context {
match result.proposal_frontier_draft.as_ref() {
Some(draft) => {
let mut target_claim_ids = clean_string_vec(&draft.target_claim_ids);
target_claim_ids.sort();
target_claim_ids.dedup();
let mut source_scope = clean_string_vec(&draft.source_scope);
source_scope.sort();
source_scope.dedup();
let mut dependency_item_ids = clean_string_vec(&draft.dependency_item_ids);
dependency_item_ids.sort();
dependency_item_ids.dedup();
let mut evidence_refs = clean_string_vec(&draft.evidence_refs);
evidence_refs.push(context.proposal_id.clone());
evidence_refs.sort();
evidence_refs.dedup();
let frontier_id = format!(
"frontier-proposal-{:x}",
sha2::Sha256::digest(context.request_id.as_bytes())
);
let proposal = epiphany_core::EpiphanyRepoModelMutationProposal::new(
format!("repo-model-mutation-proposal-{}", launch_request.job_id),
vec![
epiphany_core::EpiphanyRepoModelMutationOperation::PutFrontier {
item: epiphany_core::RepoFrontierItem {
id: frontier_id,
migration_body: draft.migration_body.trim().to_string(),
question: draft.question.trim().to_string(),
gap: draft.gap.trim().to_string(),
target_claim_ids,
source_scope,
recommended_next_organ: draft
.recommended_next_organ
.trim()
.to_string(),
adopted_plan: None,
dependency_item_ids,
status: epiphany_core::RepoFrontierStatus::Active,
evidence_refs,
public_source_refs: if draft.recommended_next_organ.trim()
== "Eyes"
{
context.public_source_refs.clone()
} else {
Vec::new()
},
created_at: Some(completed_at.to_string()),
updated_at: Some(completed_at.to_string()),
retired_at: None,
superseded_by: None,
},
let (repo_model_mutation_proposal_msgpack, repo_model_mutation_proposal_error) = if let Some(
context,
) =
proposal_modeling_context
{
match result.proposal_frontier_draft.as_ref() {
Some(draft) => {
let mut target_claim_ids = clean_string_vec(&draft.target_claim_ids);
target_claim_ids.sort();
target_claim_ids.dedup();
let mut source_scope = clean_string_vec(&draft.source_scope);
source_scope.sort();
source_scope.dedup();
let mut dependency_item_ids = clean_string_vec(&draft.dependency_item_ids);
dependency_item_ids.sort();
dependency_item_ids.dedup();
let mut evidence_refs = clean_string_vec(&draft.evidence_refs);
evidence_refs.push(context.proposal_id.clone());
evidence_refs.sort();
evidence_refs.dedup();
let frontier_id = format!(
"frontier-proposal-{:x}",
sha2::Sha256::digest(context.request_id.as_bytes())
);
let proposal = repo_model_proposal(vec![
epiphany_core::EpiphanyRepoModelMutationOperation::PutFrontier {
item: epiphany_core::RepoFrontierItem {
id: frontier_id,
migration_body: draft.migration_body.trim().to_string(),
question: draft.question.trim().to_string(),
gap: draft.gap.trim().to_string(),
target_claim_ids,
source_scope,
recommended_next_organ: draft.recommended_next_organ.trim().to_string(),
adopted_plan: None,
dependency_item_ids,
status: epiphany_core::RepoFrontierStatus::Active,
evidence_refs,
public_source_refs: if draft.recommended_next_organ.trim() == "Eyes" {
context.public_source_refs.clone()
} else {
Vec::new()
},
],
);
match proposal {
Ok(proposal) => {
encode_optional_document(&Some(proposal), "proposalFrontierDraft")
}
Err(error) => (None, Some(format!("proposalFrontierDraft: {error}"))),
created_at: Some(completed_at.to_string()),
updated_at: Some(completed_at.to_string()),
retired_at: None,
superseded_by: None,
},
},
]);
match proposal {
Ok(proposal) => {
encode_optional_document(&Some(proposal), "proposalFrontierDraft")
}
Err(error) => (None, Some(format!("proposalFrontierDraft: {error}"))),
}
None => (
None,
Some("proposalFrontierDraft: missing semantic draft".to_string()),
),
}
} else if let Some(authority) = repo_frontier_verdict_modeling_authority {
match clean_optional_string(result.frontier_verdict_gap.as_deref()) {
Some(gap) => {
let mut item = authority.frontier_item.clone();
item.gap = gap;
item.status = match authority.request.allowed_disposition {
epiphany_core::RepoFrontierVerdictDisposition::Resolved => {
epiphany_core::RepoFrontierStatus::Resolved
}
epiphany_core::RepoFrontierVerdictDisposition::Blocked => {
epiphany_core::RepoFrontierStatus::Blocked
}
};
item.updated_at = Some(completed_at.to_string());
item.evidence_refs
.push(authority.request.verification_request_id.clone());
item.evidence_refs
.push(authority.request.soul_verdict_receipt_id.clone());
item.evidence_refs.sort();
item.evidence_refs.dedup();
match epiphany_core::EpiphanyRepoModelMutationProposal::new(
format!("repo-model-mutation-proposal-{}", launch_request.job_id),
vec![
epiphany_core::EpiphanyRepoModelMutationOperation::PutFrontier { item },
],
) {
Ok(proposal) => {
encode_optional_document(&Some(proposal), "frontierVerdictGap")
}
Err(error) => (None, Some(format!("frontierVerdictGap: {error}"))),
None => (
None,
Some("proposalFrontierDraft: missing semantic draft".to_string()),
),
}
} else if let Some(authority) = repo_frontier_verdict_modeling_authority {
match clean_optional_string(result.frontier_verdict_gap.as_deref()) {
Some(gap) => {
let mut item = authority.frontier_item.clone();
item.gap = gap;
item.status = match authority.request.allowed_disposition {
epiphany_core::RepoFrontierVerdictDisposition::Resolved => {
epiphany_core::RepoFrontierStatus::Resolved
}
epiphany_core::RepoFrontierVerdictDisposition::Blocked => {
epiphany_core::RepoFrontierStatus::Blocked
}
};
item.updated_at = Some(completed_at.to_string());
item.evidence_refs
.push(authority.request.verification_request_id.clone());
item.evidence_refs
.push(authority.request.soul_verdict_receipt_id.clone());
item.evidence_refs.sort();
item.evidence_refs.dedup();
match repo_model_proposal(vec![
epiphany_core::EpiphanyRepoModelMutationOperation::PutFrontier { item },
]) {
Ok(proposal) => encode_optional_document(&Some(proposal), "frontierVerdictGap"),
Err(error) => (None, Some(format!("frontierVerdictGap: {error}"))),
}
None => (
None,
Some("frontierVerdictGap: missing semantic verdict finding".to_string()),
),
}
} else if role_id.eq_ignore_ascii_case("modeling")
&& !result.repo_model_operations.is_empty()
{
None => (
None,
Some("frontierVerdictGap: missing semantic verdict finding".to_string()),
),
}
} else if role_id.eq_ignore_ascii_case("modeling") && !result.repo_model_operations.is_empty() {
if result
.verdict
.as_deref()
.is_some_and(|verdict| verdict.eq_ignore_ascii_case("checkpoint-ready"))
&& result.repo_model_operations.iter().any(|operation| {
!matches!(
operation,
epiphany_core::EpiphanyRepoModelMutationOperation::CreateSurfaceOffer { .. }
| epiphany_core::EpiphanyRepoModelMutationOperation::DeprecateSurfaceOffer { .. }
| epiphany_core::EpiphanyRepoModelMutationOperation::WithdrawSurfaceOffer { .. }
| epiphany_core::EpiphanyRepoModelMutationOperation::CreateDependencyClaim { .. }
| epiphany_core::EpiphanyRepoModelMutationOperation::RetireDependencyClaim { .. }
)
})
{
(
None,
Some(
"repoModelOperations: checkpoint-ready may carry only local Atlas offer/claim transitions"
.to_string(),
),
)
} else {
let mut operations = result.repo_model_operations.clone();
for operation in &mut operations {
match operation {
@ -1927,26 +1961,20 @@ fn role_worker_result_from_ingress(
_ => {}
}
}
match epiphany_core::EpiphanyRepoModelMutationProposal::new(
format!("repo-model-mutation-proposal-{}", launch_request.job_id),
operations,
) {
match repo_model_proposal(operations) {
Ok(proposal) => encode_optional_document(&Some(proposal), "repoModelOperations"),
Err(error) => (None, Some(format!("repoModelOperations: {error}"))),
}
} else if !role_id.eq_ignore_ascii_case("modeling")
&& !result.repo_model_operations.is_empty()
{
(
None,
Some(
"repoModelOperations: only Modeling may propose RepoModel mutations"
.to_string(),
),
)
} else {
(None, None)
};
}
} else if !role_id.eq_ignore_ascii_case("modeling") && !result.repo_model_operations.is_empty()
{
(
None,
Some("repoModelOperations: only Modeling may propose RepoModel mutations".to_string()),
)
} else {
(None, None)
};
let (self_patch_msgpack, self_patch_error) =
encode_optional_document(&result.self_patch, "selfPatch");
let (frontier_plan_candidate_msgpack, frontier_plan_candidate_error) = if let Some(ingress) =
@ -2155,16 +2183,7 @@ fn role_worker_result_from_ingress(
scratch_summary: clean_optional_string(result.scratch_summary.as_deref()),
files_inspected: clean_string_vec(&result.files_inspected),
frontier_node_ids: clean_string_vec(&result.frontier_node_ids),
evidence_ids: {
let mut evidence_ids = clean_string_vec(&result.evidence_ids);
evidence_ids.extend(clean_string_vec(&runtime_evidence_ids));
if let Some(context) = proposal_modeling_context {
evidence_ids.push(context.proposal_id.clone());
}
evidence_ids.sort();
evidence_ids.dedup();
evidence_ids
},
evidence_ids: accepted_evidence_ids,
artifact_refs,
open_questions: clean_string_vec(&result.open_questions),
evidence_gaps: clean_string_vec(&result.evidence_gaps),
@ -2763,6 +2782,129 @@ mod tests {
Ok(())
}
#[test]
fn checkpoint_ready_modeling_carries_only_semantic_atlas_transitions() -> Result<()> {
let body = epiphany_core::RepositoryBodyObservationBasis {
schema_version: "epiphany.repository_body.v2".into(),
workspace_id: "eve".into(),
swarm_id: "gamecult-local".into(),
runtime_id: "atlas-runtime".into(),
scope: ".".into(),
body_binding_sha256: "0".repeat(64),
observation_id: "eve:1".into(),
generation: 1,
manifest_root_sha256: "1".repeat(64),
scan_started_at: "2026-08-14T00:00:00Z".into(),
scan_finished_at: "2026-08-14T00:00:01Z".into(),
};
let launch = EpiphanyRuntimeWorkerLaunchRequest {
schema_version: epiphany_core::RUNTIME_WORKER_LAUNCH_REQUEST_SCHEMA_VERSION.into(),
job_id: "atlas-modeling-job".into(),
binding_id: epiphany_core::EPIPHANY_MODELING_ROLE_BINDING_ID.into(),
role: epiphany_core::EPIPHANY_MODELING_OWNER_ROLE.into(),
authority_scope: "epiphany.role.modeling".into(),
instruction: "Model local Atlas facts.".into(),
output_contract_id: epiphany_core::ROLE_WORKER_OUTPUT_CONTRACT_ID.into(),
document_kind: "role".into(),
launch_document_msgpack: Vec::new(),
metadata: std::collections::BTreeMap::new(),
organ_launch_contract: epiphany_core::default_launch_organ_contract(
"epiphany.role.modeling",
"role",
epiphany_core::ROLE_WORKER_OUTPUT_CONTRACT_ID,
),
proposal_modeling_request_id: None,
claim_repair_request_id: None,
frontier_planning_request_id: None,
frontier_plan_mind_request_id: None,
imagination_consideration_request_id: None,
admitted_model_direction_consideration_request_id: None,
repo_frontier_modeling_request_id: None,
repo_frontier_research_request_id: None,
repo_frontier_verdict_modeling_authority_msgpack: None,
};
let atlas = RoleWorkerResultIngress {
role_id: Some("modeling".into()),
verdict: Some("checkpoint-ready".into()),
repo_model_operations: vec![
epiphany_core::EpiphanyRepoModelMutationOperation::CreateSurfaceOffer {
label: "Canonical Eve surface".into(),
contract: epiphany_core::AtlasContractDescriptor::ExactSchema {
contract_id: "eve-surface".into(),
schema_id: "gamecult.eve.surface.v1".into(),
},
source_refs: vec!["packages/eve-contracts/schema.rs".into()],
},
],
..Default::default()
};
let accepted = role_worker_result_from_ingress(
&launch,
"modeling",
Some(&body),
None,
None,
None,
None,
None,
None,
"2026-08-14T00:00:00Z",
"atlas-result",
"atlas-decision-context",
&atlas,
vec!["openai-request:atlas-test".into()],
Vec::new(),
);
assert!(accepted.item_error.is_none());
let proposal = accepted
.repo_model_mutation_proposal()?
.expect("semantic Atlas proposal");
assert_eq!(proposal.causal_request_id, launch.job_id);
assert_eq!(proposal.causal_result_id, "atlas-result");
assert_eq!(proposal.evidence_ids, ["openai-request:atlas-test"]);
assert_eq!(proposal.repository_body_observation_basis, body);
assert!(matches!(
proposal.operations()?.as_slice(),
[epiphany_core::EpiphanyRepoModelMutationOperation::CreateSurfaceOffer { .. }]
));
let hostile = RoleWorkerResultIngress {
role_id: Some("modeling".into()),
verdict: Some("checkpoint-ready".into()),
repo_model_operations: vec![
epiphany_core::EpiphanyRepoModelMutationOperation::PutFrontier {
item: epiphany_core::RepoFrontierItem::default(),
},
],
..Default::default()
};
let refused = role_worker_result_from_ingress(
&launch,
"modeling",
Some(&body),
None,
None,
None,
None,
None,
None,
"2026-08-14T00:00:00Z",
"hostile-result",
"hostile-decision-context",
&hostile,
Vec::new(),
Vec::new(),
);
assert!(refused.repo_model_mutation_proposal_msgpack.is_none());
assert!(
refused
.item_error
.as_deref()
.is_some_and(|error| error.contains("only local Atlas"))
);
Ok(())
}
#[test]
fn proposal_modeling_request_carries_narrow_schema_only_as_response_format() -> Result<()> {
let context = epiphany_core::RepoFrontierProposalModelingContextProjection {
@ -3117,6 +3259,10 @@ mod tests {
frontier: Vec::new(),
lifecycle_receipts: Vec::new(),
claim_obligations: Vec::new(),
surface_offers: Vec::new(),
dependency_claims: Vec::new(),
dependency_verifications: Vec::new(),
dependency_impacts: Vec::new(),
},
};
let launch = EpiphanyRuntimeWorkerLaunchRequest {

View file

@ -4702,6 +4702,51 @@ blast radius. A consumer ingress re-reads its local claim and the exact
projection before committing an impact and asking Resident Self for a bounded
Modeling or Soul wake. The wake explicitly grants no Hands authority.
Ordinary Modeling authors offers and claims through
`EpiphanyRepoModelMutationOperation`. The model supplies only a semantic
transition, a display label, a closed contract/requirement, and sorted current
repository-relative source paths. The OpenAI runtime constructs
`epiphany.repo_model.mutation_proposal.v2` from the exact launch request,
terminal result, evidence identifiers, and sealed Body basis. The keyed planner
requires that basis to equal the live runtime Body observation, authenticates
its manifest, resolves every source path to the exact raw file digest, derives
the opaque UUID, and then emits the Mind strong reads and writes. The publisher
independently revalidates the stored Body references against the current
manifest before exporting them. Body drift therefore refuses both stale local
admission and stale federation; no eventual repair loop owns correctness.
The entanglement projection carries the current endpoint labels, exact claim
requirement and offer contract, offer lifecycle, both endpoint Body evidence
sets, and only the Soul publication/evidence that matches the exact current
claim and offer versions. Eve derives its attention age from the projection's
evaluation time and endpoint publisher heartbeats, then shows contracts, Body
evidence, Soul evidence, cycles, blast radius, source publications, and
watermarks in the same retained tree.
Atlas authority map:
- Owner: each local Modeling/Mind pair owns its offers and claims; Soul/Mind
owns exact verification; the projector owns deterministic derivation only.
- Inputs: semantic Modeling operations, the exact causal request/result and
evidence IDs, current authenticated Body basis and manifest, signed local
publications, pinned trust, and audience visibility.
- Outputs: keyed local facts, signed immutable publications, one deterministic
projection, exact local impacts, and bounded Self pressure.
- Derived state: shared edges, compatibility, freshness, cycles, blast radius,
attention age, and Eve views. None can rewrite an endpoint fact.
- Forbidden writers: models cannot choose IDs/digests/CAS; publishers cannot
open foreign Mind stores; Odin cannot derive edges; the projector cannot
mutate dependencies; Atlas cannot grant Hands authority.
- Shared paths: direct model completion and resident Modeling completion use
the same proposal-v2 constructor and keyed planner; publisher and impact
ingress re-read the same typed local facts before consequence.
- Cut line: aggregate memory-graph authority, `RepoModelPatch`, model-authored
revision/timestamp/receipt fields, and foreign-store reads remain absent.
- Verification layer: CAS/body-drift refusals prove local ownership; signature,
replay, trust, determinism, cycle, partition, transitive-radius, Eve
conformance, wake-dedupe, cooldown, brake, and no-Hands tests prove the
federation boundary.
The provider-owned Eve projection is one `gamecult.eve.surface.v1` retained
tree with attention, drilldown, and secondary graph views. Select/filter are
presentation-only; domain mutation routes back to the owning repository's

View file

@ -49,6 +49,30 @@ No organ opens another repository's Mind store. Publishers read only their own
runtime Mind store. The projector reads Odin. Impact ingress reads the
projection plus its own local claims.
## Modeling authoring and Body evidence
Ordinary Modeling is the sole production authoring path for offers and claims.
Its model output names only semantic operations: create, deprecate, withdraw,
or retire. Creation includes a human label, a closed contract shape, and a
non-empty sorted set of repository-relative source paths. It cannot supply
UUIDs, source digests, causal identifiers, Body bases, CAS reads, timestamps,
receipts, or writes.
The runtime constructs `epiphany.repo_model.mutation_proposal.v2` from the
exact worker request, exact result, ordered evidence identifiers, and the Body
basis sealed into the launch. The keyed planner re-reads the current Body
basis, authenticates the manifest, resolves every requested source path to its
raw SHA-256, derives opaque UUIDv5 identities, and produces the exact Mind CAS.
An old Body observation or changed source refuses before any document is
written.
The publisher repeats the Body check at the federation boundary. It refuses to
publish an offer or claim unless every stored source path and digest still
matches the current authenticated Body manifest. The projector retains those
endpoint labels, contracts, lifecycle states, and Body references alongside
the exact applicable Soul evidence. Eve can therefore show why an edge exists,
not merely that the projector drew one.
## Invariants
- Repository identity is
@ -68,6 +92,9 @@ projection plus its own local claims.
- Local offer, claim, verification, and impact writes use dedicated typed
planners and exact CultCache CAS. A stale Body or source version refuses the
entire mutation.
- Model-authored offer and claim operations contain semantic intent and source
paths only. Runtime-owned proposal v2 binds exact cause, evidence, current
Body basis, resolved source digests, derived identities, and CAS authority.
- Publications bind repository, runtime incarnation, Body basis, Verse,
source schema/key/version/digest, Mind receipt, canonical payload digest,
publication time, and service signature.
@ -120,9 +147,14 @@ pinned by exact repository coordinates; key rotation is operator-gated.
## Rollout gates
1. Engage all three Atlas brake scopes. Run the three publishers, projector,
and impact ingresses against isolated pilot stores. Inspect publications,
watermarks, rejections, and the retained Eve tree without lane scheduling.
1. Keep impact ingress absent. Let ordinary Modeling admit the three local seed
facts into isolated Mind stores, then run the publishers and projector until
signed publications, exact watermarks, and the retained Eve tree exist.
Engage `atlas.publish`, `atlas.project`, and `atlas.impact_ingress`, run one
more publisher/projector cycle plus the first ingress cycle, and prove every
write/schedule is held while the last projection remains visibly stale and
read-only. A brake cannot both forbid the first publication and prove that a
publication exists; ordering is part of the invariant.
2. Release Atlas scopes for Modeling and Soul while leaving existing Hands
authorization unchanged. A temporary Eve contract change must wake Odin
Modeling and then Epiphany Modeling without an operator prompt.
@ -132,8 +164,9 @@ pinned by exact repository coordinates; key rotation is operator-gated.
4. Only after sustained local proof, register topology and recovery runbooks in
`gamecult-ops`. Yggdrasil and the public Verse remain outside V1.
The implementation and isolated proofs close the code slice. Gates 2 through 4
are operational evidence, not claims that can be manufactured by unit tests.
The implementation and isolated proofs close the code slice. All four rollout
gates are operational evidence, not claims that can be manufactured by unit
tests.
## Verification
@ -141,8 +174,11 @@ The focused proofs cover:
- no production `RepoModelPatch`, aggregate RepoModel store, aggregate
admission reader/writer, or aggregate memory-graph key;
- runtime-owned semantic Modeling ingress and exact keyed reasoning bases;
- local offer/claim admission through current real Body evidence and Mind CAS;
- runtime-owned proposal-v2 construction from exact request, result, evidence,
and launch Body basis; models provide semantic operations only;
- local offer/claim admission through current authenticated Body manifests,
resolved source digests, derived UUIDs, exact reasoning bases, and Mind CAS;
- publisher refusal after local Body evidence drifts;
- signature tamper, trust-coordinate substitution, rollback, replay,
watermark, and payload-size refusal;
- order-independent projection digests, closed compatibility, verification
@ -154,8 +190,13 @@ The focused proofs cover:
informational visibility without wake, and absence of Hands authority;
- Odin persistence of only the registered Atlas/projection/Eve schemas without
Odin-authored edges;
- Eve conformance for one canonical GUI/TUI tree with presentation-only select
and filter commands.
- Eve conformance for one canonical GUI/TUI tree with endpoint contracts,
source evidence, exact Soul evidence, publisher age/watermarks, cycles, blast
radius, and presentation-only select/filter commands.
Current counts are Epiphany core 555/555, OpenAI Modeling ingress 23/23,
coordinator 18/18, Odin Node 1/1 plus Rust 15/15, and Eve Atlas 4/4 plus Eve
contracts 6/6. The ordinary Epiphany all-target workspace check also passes.
Current verification commands: