Delete counterfeit Hands review authority

This commit is contained in:
Meta Vens 2026-08-24 23:21:26 +02:00
commit a01c684262
9 changed files with 106 additions and 487 deletions

View file

@ -4,7 +4,6 @@ use anyhow::anyhow;
use chrono::SecondsFormat;
use epiphany_core::COORDINATOR_RUN_RECEIPT_TYPE;
use epiphany_core::EpiphanyCoordinatorRunReceipt;
use epiphany_core::HANDS_ACTION_INTENT_SCHEMA_VERSION;
use epiphany_core::HANDS_COMMAND_RECEIPT_TYPE;
use epiphany_core::HANDS_COMMIT_RECEIPT_TYPE;
use epiphany_core::HANDS_PATCH_RECEIPT_TYPE;
@ -13,12 +12,10 @@ use epiphany_core::RepoFrontierHandsAuthority;
use epiphany_core::RuntimeSpineInitOptions;
use epiphany_core::coordinator_status as status_projection;
use epiphany_core::finalize_coordinator_run;
use epiphany_core::hands_action_review_for_intent;
use epiphany_core::initialize_runtime_spine;
use epiphany_core::load_epiphany_cultmesh_swarm_brake;
use epiphany_core::open_coordinator_run;
use epiphany_core::put_hands_action_intent;
use epiphany_core::put_hands_action_review;
use epiphany_core::put_repo_frontier_hands_authority;
use epiphany_core::put_substrate_gate_repo_access_grant_receipt;
use epiphany_core::select_and_commit_repo_frontier_route;
@ -1533,71 +1530,17 @@ fn record_hands_implementation_gate(
put_substrate_gate_repo_access_grant_receipt(runtime_store, &substrate_grant)?;
let intent = HandsActionIntent {
schema_version: HANDS_ACTION_INTENT_SCHEMA_VERSION.to_string(),
intent_id: format!("hands-intent-{suffix}"),
runtime_job_id: runtime_job_id.clone(),
binding_id: "implementation-worker".to_string(),
role: "epiphany-hands".to_string(),
authority_scope: "epiphany.role.implementation".to_string(),
requested_action: "continueImplementation".to_string(),
requested_paths: requested_paths.clone(),
substrate_gate_grant_receipt_id: grant_id.clone(),
requested_at: requested_at.clone(),
contract: "Coordinator continuation becomes a typed Hands action intent before any file edit, command, or commit may count as implementation evidence."
.to_string(),
frontier_route_id: route
.adopted_plan
.as_ref()
.map(|_| route.route_id.clone())
.unwrap_or_default(),
plan_candidate_sha256: route
.adopted_plan
.as_ref()
.map(|plan| plan.candidate_sha256.clone())
.unwrap_or_default(),
plan_action: route
.adopted_plan
.as_ref()
.map(|plan| plan.effective_action().to_string())
.unwrap_or_default(),
};
put_hands_action_intent(runtime_store, &intent)?;
let mut review = hands_action_review_for_intent(
format!("hands-review-{suffix}"),
&intent,
"approved".to_string(),
vec![
"patch".to_string(),
"command".to_string(),
"commit".to_string(),
],
vec![
"Coordinator selected continueImplementation for the current thread state."
.to_string(),
"Hands remains the action owner; Mind and Soul still own state admission and verification."
.to_string(),
],
requested_at,
);
review.required_receipts = vec![
HANDS_PATCH_RECEIPT_TYPE.to_string(),
HANDS_COMMAND_RECEIPT_TYPE.to_string(),
HANDS_COMMIT_RECEIPT_TYPE.to_string(),
];
put_hands_action_review(runtime_store, &review)?;
let authority = RepoFrontierHandsAuthority {
authority_id: format!("repo-frontier-hands-authority-{}", intent.intent_id),
route_id: route.route_id.clone(),
model_projection_digest: route.model_projection_digest.clone(),
model_source_documents: route.model_source_documents.clone(),
frontier_item_id: route.frontier_item_id.clone(),
frontier_item_hash: route.frontier_item_hash.clone(),
hands_intent_id: intent.intent_id.clone(),
hands_review_id: review.review_id.clone(),
substrate_grant_receipt_id: grant_id.clone(),
requested_paths: requested_paths.clone(),
granted_at: review.reviewed_at.clone(),
};
put_repo_frontier_hands_authority(runtime_store, &authority)?;
@ -1606,13 +1549,12 @@ fn record_hands_implementation_gate(
"runtimeJobId": runtime_job_id,
"substrateGateGrantReceiptId": grant_id,
"intentId": intent.intent_id,
"reviewId": review.review_id,
"routeId": route.route_id,
"modelProjectionDigest": route.model_projection_digest,
"modelSourceDocuments": route.model_source_documents,
"frontierItemId": route.frontier_item_id,
"requestedPaths": requested_paths,
"requiredReceipts": review.required_receipts,
"requiredReceipts": [HANDS_PATCH_RECEIPT_TYPE, HANDS_COMMAND_RECEIPT_TYPE, HANDS_COMMIT_RECEIPT_TYPE],
"plannedAction": route.adopted_plan.as_ref().map(|plan| plan.effective_action()),
"plannedCommand": route.adopted_plan.as_ref().map(|plan| plan.effective_command()),
"originalPlannedAction": route.adopted_plan.as_ref().map(|plan| plan.action.as_str()),

View file

@ -1523,10 +1523,6 @@ pub fn launch_current_frontier_verification_work(
crate::HandsActionIntent::TYPE,
request.hands_intent_id.as_str(),
),
(
crate::HandsActionReview::TYPE,
request.hands_review_id.as_str(),
),
(
crate::HandsPatchReceipt::TYPE,
request.hands_patch_receipt_id.as_str(),
@ -2026,10 +2022,6 @@ pub fn accept_frontier_verification_result(
crate::HandsActionIntent::TYPE,
request.hands_intent_id.as_str(),
),
(
crate::HandsActionReview::TYPE,
request.hands_review_id.as_str(),
),
(
crate::HandsPatchReceipt::TYPE,
request.hands_patch_receipt_id.as_str(),
@ -4377,63 +4369,30 @@ mod tests {
);
crate::put_substrate_gate_repo_access_grant_receipt(&store, &grant)?;
let intent = crate::HandsActionIntent {
schema_version: crate::HANDS_ACTION_INTENT_SCHEMA_VERSION.into(),
intent_id: "hands-intent-verification-fixture".into(),
runtime_job_id: hands_job_id.into(),
binding_id: "implementation-worker".into(),
role: "epiphany-hands".into(),
authority_scope: "epiphany.role.implementation".into(),
requested_action: "continueImplementation".into(),
requested_paths: route.authorized_paths.clone(),
substrate_gate_grant_receipt_id: grant.receipt_id.clone(),
requested_at: "2026-08-17T00:00:14.200Z".into(),
contract: "The exact Hands consequence under Verification.".into(),
frontier_route_id: String::new(),
plan_candidate_sha256: String::new(),
plan_action: String::new(),
};
crate::put_hands_action_intent(&store, &intent)?;
let mut hands_review = crate::hands_action_review_for_intent(
"hands-review-verification-fixture".into(),
&intent,
"approved".into(),
vec!["patch".into(), "command".into(), "commit".into()],
vec!["Bounded fixture consequence is authorized.".into()],
"2026-08-17T00:00:14.300Z".into(),
);
hands_review.required_receipts = vec![
crate::HANDS_PATCH_RECEIPT_TYPE.into(),
crate::HANDS_COMMAND_RECEIPT_TYPE.into(),
crate::HANDS_COMMIT_RECEIPT_TYPE.into(),
];
crate::put_hands_action_review(&store, &hands_review)?;
let hands_authority = crate::RepoFrontierHandsAuthority {
authority_id: "repo-frontier-hands-authority-verification-fixture".into(),
route_id: route.route_id.clone(),
model_projection_digest: route.model_projection_digest.clone(),
model_source_documents: route.model_source_documents.clone(),
frontier_item_id: route.frontier_item_id.clone(),
frontier_item_hash: route.frontier_item_hash.clone(),
hands_intent_id: intent.intent_id.clone(),
hands_review_id: hands_review.review_id.clone(),
substrate_grant_receipt_id: grant.receipt_id.clone(),
requested_paths: route.authorized_paths.clone(),
granted_at: hands_review.reviewed_at.clone(),
};
crate::put_repo_frontier_hands_authority(&store, &hands_authority)?;
let hands_patch = crate::hands_patch_receipt_for_review(
let hands_patch = crate::hands_patch_receipt_for_intent(
"hands-patch-verification-fixture".into(),
&intent,
&hands_review,
route.authorized_paths.clone(),
"Applied the exact bounded change.".into(),
"2026-08-17T00:00:14.400Z".into(),
);
crate::put_hands_patch_receipt(&store, &hands_patch)?;
let hands_command = crate::hands_command_receipt_for_review(
let hands_command = crate::hands_command_receipt_for_intent(
"hands-command-verification-fixture".into(),
&intent,
&hands_review,
"cargo test exact-verification-fixture".into(),
"0".into(),
"verification.stdout".into(),
@ -4442,16 +4401,26 @@ mod tests {
"2026-08-17T00:00:14.500Z".into(),
);
crate::put_hands_command_receipt(&store, &hands_command)?;
let hands_commit = crate::hands_commit_receipt_for_review(
let hands_commit = crate::hands_commit_receipt_for_intent(
"hands-commit-verification-fixture".into(),
&intent,
&hands_review,
"0123456789abcdef0123456789abcdef01234567".into(),
"codex/verification-fixture".into(),
route.authorized_paths.clone(),
"Committed the exact bounded consequence.".into(),
"2026-08-17T00:00:14.600Z".into(),
);
let ambiguous_hands_store = temp.path().join("ambiguous-hands.cc");
std::fs::copy(&store, &ambiguous_hands_store)?;
let mut duplicate_patch = hands_patch.clone();
duplicate_patch.receipt_id = "hands-patch-verification-fixture-duplicate".into();
crate::put_hands_patch_receipt(&ambiguous_hands_store, &duplicate_patch)?;
assert!(
crate::put_hands_commit_receipt(&ambiguous_hands_store, &hands_commit)
.unwrap_err()
.to_string()
.contains("one exact patch receipt")
);
let persona_cultmesh = temp.path().join("persona-concurrency-cultmesh.cc");
crate::write_epiphany_cultmesh_swarm_brake(
&persona_cultmesh,

View file

@ -3,63 +3,17 @@ use cultcache_rs::DatabaseEntry;
pub const HANDS_COMMAND_RECEIPT_TYPE: &str = "epiphany.hands.command_receipt";
pub const HANDS_PATCH_RECEIPT_TYPE: &str = "epiphany.hands.patch_receipt";
pub const HANDS_COMMIT_RECEIPT_TYPE: &str = "epiphany.hands.commit_receipt";
pub const HANDS_ACTION_INTENT_SCHEMA_VERSION: &str = "epiphany.hands.action_intent.v1";
pub const HANDS_ACTION_REVIEW_SCHEMA_VERSION: &str = "epiphany.hands.action_review.v0";
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(type = "epiphany.hands.action_intent", schema = "HandsActionIntent")]
pub struct HandsActionIntent {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub intent_id: String,
#[cultcache(key = 2)]
#[cultcache(key = 1)]
pub runtime_job_id: String,
#[cultcache(key = 3)]
pub binding_id: String,
#[cultcache(key = 4)]
pub role: String,
#[cultcache(key = 5)]
pub authority_scope: String,
#[cultcache(key = 6)]
pub requested_action: String,
#[cultcache(key = 7)]
pub requested_paths: Vec<String>,
#[cultcache(key = 8)]
pub substrate_gate_grant_receipt_id: String,
#[cultcache(key = 9)]
pub requested_at: String,
#[cultcache(key = 10)]
pub contract: String,
#[cultcache(key = 11, default)]
pub frontier_route_id: String,
#[cultcache(key = 12, default)]
pub plan_candidate_sha256: String,
#[cultcache(key = 13, default)]
pub plan_action: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(type = "epiphany.hands.action_review", schema = "HandsActionReview")]
pub struct HandsActionReview {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub review_id: String,
#[cultcache(key = 2)]
pub intent_id: String,
pub requested_paths: Vec<String>,
#[cultcache(key = 3)]
pub decision: String,
#[cultcache(key = 4)]
pub allowed_operations: Vec<String>,
#[cultcache(key = 5)]
pub required_receipts: Vec<String>,
#[cultcache(key = 6)]
pub reasons: Vec<String>,
#[cultcache(key = 7)]
pub reviewed_at: String,
#[cultcache(key = 8)]
pub contract: String,
pub substrate_gate_grant_receipt_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
@ -70,16 +24,10 @@ pub struct HandsPatchReceipt {
#[cultcache(key = 1)]
pub intent_id: String,
#[cultcache(key = 2)]
pub review_id: String,
#[cultcache(key = 3)]
pub substrate_gate_grant_receipt_id: String,
#[cultcache(key = 4)]
pub runtime_job_id: String,
#[cultcache(key = 5)]
pub changed_paths: Vec<String>,
#[cultcache(key = 6)]
#[cultcache(key = 3)]
pub summary: String,
#[cultcache(key = 7)]
#[cultcache(key = 4)]
pub emitted_at: String,
}
@ -94,22 +42,16 @@ pub struct HandsCommandReceipt {
#[cultcache(key = 1)]
pub intent_id: String,
#[cultcache(key = 2)]
pub review_id: String,
#[cultcache(key = 3)]
pub substrate_gate_grant_receipt_id: String,
#[cultcache(key = 4)]
pub runtime_job_id: String,
#[cultcache(key = 5)]
pub command: String,
#[cultcache(key = 6)]
#[cultcache(key = 3)]
pub exit_code: String,
#[cultcache(key = 7)]
#[cultcache(key = 4)]
pub stdout_artifact: String,
#[cultcache(key = 8)]
#[cultcache(key = 5)]
pub stderr_artifact: String,
#[cultcache(key = 9)]
#[cultcache(key = 6)]
pub summary: String,
#[cultcache(key = 10)]
#[cultcache(key = 7)]
pub emitted_at: String,
}
@ -121,46 +63,20 @@ pub struct HandsCommitReceipt {
#[cultcache(key = 1)]
pub intent_id: String,
#[cultcache(key = 2)]
pub review_id: String,
#[cultcache(key = 3)]
pub runtime_job_id: String,
#[cultcache(key = 4)]
pub commit_sha: String,
#[cultcache(key = 5)]
#[cultcache(key = 3)]
pub branch: String,
#[cultcache(key = 6)]
#[cultcache(key = 4)]
pub changed_paths: Vec<String>,
#[cultcache(key = 7)]
#[cultcache(key = 5)]
pub summary: String,
#[cultcache(key = 8)]
#[cultcache(key = 6)]
pub emitted_at: String,
}
pub fn hands_action_review_for_intent(
review_id: String,
intent: &HandsActionIntent,
decision: String,
allowed_operations: Vec<String>,
reasons: Vec<String>,
reviewed_at: String,
) -> HandsActionReview {
HandsActionReview {
schema_version: HANDS_ACTION_REVIEW_SCHEMA_VERSION.to_string(),
review_id,
intent_id: intent.intent_id.clone(),
decision,
allowed_operations,
required_receipts: vec![HANDS_PATCH_RECEIPT_TYPE.to_string()],
reasons,
reviewed_at,
contract: "Hands review is the execution decision for a bounded action intent; it depends on Substrate Gate access and does not admit durable Mind state.".to_string(),
}
}
pub fn hands_patch_receipt_for_review(
pub fn hands_patch_receipt_for_intent(
receipt_id: String,
intent: &HandsActionIntent,
review: &HandsActionReview,
changed_paths: Vec<String>,
summary: String,
emitted_at: String,
@ -168,9 +84,6 @@ pub fn hands_patch_receipt_for_review(
HandsPatchReceipt {
receipt_id,
intent_id: intent.intent_id.clone(),
review_id: review.review_id.clone(),
substrate_gate_grant_receipt_id: intent.substrate_gate_grant_receipt_id.clone(),
runtime_job_id: intent.runtime_job_id.clone(),
changed_paths,
summary,
emitted_at,
@ -178,10 +91,9 @@ pub fn hands_patch_receipt_for_review(
}
#[allow(clippy::too_many_arguments)]
pub fn hands_command_receipt_for_review(
pub fn hands_command_receipt_for_intent(
receipt_id: String,
intent: &HandsActionIntent,
review: &HandsActionReview,
command: String,
exit_code: String,
stdout_artifact: String,
@ -192,9 +104,6 @@ pub fn hands_command_receipt_for_review(
HandsCommandReceipt {
receipt_id,
intent_id: intent.intent_id.clone(),
review_id: review.review_id.clone(),
substrate_gate_grant_receipt_id: intent.substrate_gate_grant_receipt_id.clone(),
runtime_job_id: intent.runtime_job_id.clone(),
command,
exit_code,
stdout_artifact,
@ -204,10 +113,9 @@ pub fn hands_command_receipt_for_review(
}
}
pub fn hands_commit_receipt_for_review(
pub fn hands_commit_receipt_for_intent(
receipt_id: String,
intent: &HandsActionIntent,
review: &HandsActionReview,
commit_sha: String,
branch: String,
changed_paths: Vec<String>,
@ -217,8 +125,6 @@ pub fn hands_commit_receipt_for_review(
HandsCommitReceipt {
receipt_id,
intent_id: intent.intent_id.clone(),
review_id: review.review_id.clone(),
runtime_job_id: intent.runtime_job_id.clone(),
commit_sha,
branch,
changed_paths,

View file

@ -247,7 +247,6 @@ pub use runtime_spine::open_runtime_model_execution;
pub use runtime_spine::prepare_runtime_spine_heartbeat_job;
pub(crate) use runtime_spine::promote_autonomous_direction_options_for_modeling;
pub use runtime_spine::put_hands_action_intent;
pub use runtime_spine::put_hands_action_review;
pub use runtime_spine::put_hands_command_receipt;
pub use runtime_spine::put_hands_commit_receipt;
pub use runtime_spine::put_hands_patch_receipt;

View file

@ -434,21 +434,7 @@ pub struct RepoFrontierHandsAuthority {
#[cultcache(key = 2)]
pub route_id: String,
#[cultcache(key = 3)]
pub model_projection_digest: String,
#[cultcache(key = 4)]
pub model_source_documents: Vec<crate::EpiphanyMindDocumentVersion>,
#[cultcache(key = 5)]
pub frontier_item_id: String,
#[cultcache(key = 6)]
pub frontier_item_hash: String,
#[cultcache(key = 7)]
pub hands_intent_id: String,
#[cultcache(key = 8)]
pub hands_review_id: String,
#[cultcache(key = 9)]
#[cultcache(key = 4)]
pub substrate_grant_receipt_id: String,
#[cultcache(key = 10)]
pub requested_paths: Vec<String>,
#[cultcache(key = 11)]
pub granted_at: String,
}

View file

@ -55,7 +55,7 @@ pub const COORDINATOR_RUN_RECEIPT_TYPE: &str = "epiphany.coordinator_run_receipt
pub const RUNTIME_IDENTITY_KEY: &str = "self";
pub const RUNTIME_SWARM_BINDING_KEY: &str = "runtime-swarm-binding";
pub const RUNTIME_SWARM_BINDING_SCHEMA_VERSION: &str = "epiphany.runtime.swarm_binding.v1";
pub const RUNTIME_SPINE_SCHEMA_VERSION: &str = "epiphany.runtime_spine.v45";
pub const RUNTIME_SPINE_SCHEMA_VERSION: &str = "epiphany.runtime_spine.v46";
pub const EPIPHANY_RUNTIME_ROOT_SESSION_ID: &str = "epiphany-main";
#[derive(Clone, Debug, PartialEq, DatabaseEntry)]
#[cultcache(type = "epiphany.runtime.identity", schema = "EpiphanyRuntimeIdentity")]
@ -696,7 +696,6 @@ fn runtime_spine_schema_cache() -> Result<CultCache> {
cache.register_entry_type::<EpiphanyCoordinatorDeathRecovery>()?;
cache.register_entry_type::<SubstrateGateRepoAccessGrantReceipt>()?;
cache.register_entry_type::<HandsActionIntent>()?;
cache.register_entry_type::<HandsActionReview>()?;
cache.register_entry_type::<HandsPatchReceipt>()?;
cache.register_entry_type::<HandsCommandReceipt>()?;
cache.register_entry_type::<HandsCommitReceipt>()?;
@ -2610,9 +2609,7 @@ pub(crate) fn frontier_verification_request_for_launch(
|| carried.route.route_id != request.route_id
|| carried.hands_authority.route_id != request.route_id
|| carried.hands_authority.hands_intent_id != request.hands_intent_id
|| carried.hands_authority.hands_review_id != request.hands_review_id
|| carried.hands_intent.intent_id != request.hands_intent_id
|| carried.hands_review.review_id != request.hands_review_id
|| carried.patch_receipt.receipt_id != request.hands_patch_receipt_id
|| carried.command_receipt.receipt_id != request.hands_command_receipt_id
|| carried.commit_receipt.receipt_id != request.hands_commit_receipt_id
@ -6810,24 +6807,13 @@ pub fn put_hands_action_intent(
) -> Result<()> {
validate_non_empty(&intent.intent_id, "Hands action intent id")?;
validate_non_empty(&intent.runtime_job_id, "Hands action runtime job")?;
validate_non_empty(&intent.binding_id, "Hands action binding")?;
validate_non_empty(&intent.role, "Hands action role")?;
validate_non_empty(&intent.authority_scope, "Hands action authority scope")?;
validate_non_empty(&intent.requested_action, "Hands requested action")?;
validate_non_empty(
&intent.substrate_gate_grant_receipt_id,
"Hands Substrate Gate grant receipt",
)?;
validate_non_empty(&intent.requested_at, "Hands action requested timestamp")?;
if intent.requested_paths.is_empty() {
return Err(anyhow!("Hands action intent must name requested paths"));
}
if intent.schema_version != HANDS_ACTION_INTENT_SCHEMA_VERSION
|| chrono::DateTime::parse_from_rfc3339(&intent.requested_at).is_err()
|| intent.contract.trim().is_empty()
{
return Err(anyhow!("invalid Hands action intent contract"));
}
let store_path = store_path.as_ref();
let mut cache = runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
@ -6838,9 +6824,6 @@ pub fn put_hands_action_intent(
anyhow!("Hands action intent requires its persisted Substrate Gate grant")
})?;
if grant.runtime_job_id != intent.runtime_job_id
|| grant.binding_id != intent.binding_id
|| grant.role != intent.role
|| grant.authority_scope != intent.authority_scope
|| !grant
.granted_operations
.iter()
@ -6870,40 +6853,6 @@ pub fn put_hands_action_intent(
}
}
pub fn put_hands_action_review(
store_path: impl AsRef<Path>,
review: &HandsActionReview,
) -> Result<()> {
validate_non_empty(&review.review_id, "Hands action review id")?;
validate_non_empty(&review.intent_id, "Hands action review intent")?;
validate_non_empty(&review.decision, "Hands action review decision")?;
validate_non_empty(&review.reviewed_at, "Hands action review timestamp")?;
if review.allowed_operations.is_empty() {
return Err(anyhow!("Hands action review must name allowed operations"));
}
if review.schema_version != HANDS_ACTION_REVIEW_SCHEMA_VERSION
|| chrono::DateTime::parse_from_rfc3339(&review.reviewed_at).is_err()
|| review.contract.trim().is_empty()
{
return Err(anyhow!("invalid Hands action review contract"));
}
let store_path = store_path.as_ref();
let mut cache = runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
require_identity(&cache)?;
let (envelope, _) = cache.prepare_entry(&review.review_id, review)?;
let backing = SingleFileMessagePackBackingStore::new(store_path);
if backing.compare_and_swap_batch(&[], vec![envelope])? {
return Ok(());
}
let mut reloaded = runtime_spine_cache(store_path)?;
reloaded.pull_all_backing_stores()?;
match reloaded.get::<HandsActionReview>(&review.review_id)? {
Some(existing) if existing == *review => Ok(()),
_ => Err(anyhow!("Hands action review ids are immutable")),
}
}
fn validate_repo_frontier_hands_authority_chain(
cache: &CultCache,
authority: &RepoFrontierHandsAuthority,
@ -6937,80 +6886,28 @@ fn validate_repo_frontier_hands_authority_chain(
let intent = cache
.get::<HandsActionIntent>(&authority.hands_intent_id)?
.ok_or_else(|| anyhow!("Hands authority requires its persisted intent"))?;
let review = cache
.get::<HandsActionReview>(&authority.hands_review_id)?
.ok_or_else(|| anyhow!("Hands authority requires its persisted review"))?;
let grant = cache
.get::<SubstrateGateRepoAccessGrantReceipt>(&authority.substrate_grant_receipt_id)?
.ok_or_else(|| anyhow!("Hands authority requires its persisted Substrate grant"))?;
let within_scope = authority.requested_paths.iter().all(|path| {
route.authorized_paths.iter().any(|scope| {
path == scope || path.starts_with(&format!("{}/", scope.trim_end_matches(['/', '\\'])))
})
});
let requested_operations: &[&str] = match intent.requested_action.as_str() {
"patch" => &["patch"],
"continueImplementation" => &["patch", "command", "commit"],
_ => {
return Err(anyhow!(
"Hands authority names an unsupported requested action"
));
}
};
let adopted_plan_binding_is_exact = match route.adopted_plan.as_ref() {
Some(plan) => {
intent.frontier_route_id == route.route_id
&& intent.plan_candidate_sha256 == plan.candidate_sha256
&& intent.plan_action == plan.effective_action()
}
None => {
intent.frontier_route_id.is_empty()
&& intent.plan_candidate_sha256.is_empty()
&& intent.plan_action.is_empty()
}
};
if intent.schema_version != HANDS_ACTION_INTENT_SCHEMA_VERSION
|| review.schema_version != HANDS_ACTION_REVIEW_SCHEMA_VERSION
|| grant.schema_version != SUBSTRATE_GATE_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION
|| intent.contract.trim().is_empty()
|| review.contract.trim().is_empty()
if grant.schema_version != SUBSTRATE_GATE_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION
|| grant.contract.trim().is_empty()
|| chrono::DateTime::parse_from_rfc3339(&intent.requested_at).is_err()
|| chrono::DateTime::parse_from_rfc3339(&review.reviewed_at).is_err()
|| chrono::DateTime::parse_from_rfc3339(&grant.granted_at).is_err()
|| route.next_organ != RepoFrontierNextOrgan::Hands
|| authority.model_projection_digest != route.model_projection_digest
|| authority.model_source_documents != route.model_source_documents
|| authority.frontier_item_id != route.frontier_item_id
|| authority.frontier_item_hash != route.frontier_item_hash
|| current_item.adopted_plan != route.adopted_plan
|| route
.adopted_plan
.as_ref()
.is_some_and(|plan| route.authorized_paths != plan.safe_paths)
|| !adopted_plan_binding_is_exact
|| review.intent_id != intent.intent_id
|| review.decision != "approved"
|| !requested_operations.iter().all(|required| {
review
.allowed_operations
.iter()
.any(|operation| operation == required)
})
|| intent.substrate_gate_grant_receipt_id != grant.receipt_id
|| grant.runtime_job_id != intent.runtime_job_id
|| grant.binding_id != intent.binding_id
|| grant.role != intent.role
|| grant.authority_scope != intent.authority_scope
|| !requested_operations.iter().all(|required| {
|| !["patch", "command", "commit"].iter().all(|required| {
grant
.granted_operations
.iter()
.any(|operation| operation == required)
})
|| authority.requested_paths != intent.requested_paths
|| authority.requested_paths != grant.granted_paths
|| !within_scope
|| intent.requested_paths != grant.granted_paths
|| intent.requested_paths != route.authorized_paths
{
return Err(anyhow!(
"repo frontier Hands authority chain violates its full authority contract"
@ -7024,9 +6921,14 @@ pub fn put_repo_frontier_hands_authority(
authority: &RepoFrontierHandsAuthority,
) -> Result<()> {
let store_path = store_path.as_ref();
if chrono::DateTime::parse_from_rfc3339(&authority.granted_at).is_err()
|| !crate::memory_graph::repo_paths_are_canonical_and_safe(&authority.requested_paths)
|| authority.requested_paths.is_empty()
if [
authority.authority_id.as_str(),
authority.route_id.as_str(),
authority.hands_intent_id.as_str(),
authority.substrate_grant_receipt_id.as_str(),
]
.into_iter()
.any(str::is_empty)
{
return Err(anyhow!("invalid repo frontier Hands authority contract"));
}
@ -7040,40 +6942,11 @@ pub fn put_repo_frontier_hands_authority(
let intent = cache
.get::<HandsActionIntent>(&authority.hands_intent_id)?
.ok_or_else(|| anyhow!("repo frontier Hands authority requires its persisted intent"))?;
let review = cache
.get::<HandsActionReview>(&authority.hands_review_id)?
.ok_or_else(|| anyhow!("repo frontier Hands authority requires its persisted review"))?;
let grant = cache
.get::<SubstrateGateRepoAccessGrantReceipt>(&authority.substrate_grant_receipt_id)?
.ok_or_else(|| {
anyhow!("repo frontier Hands authority requires its persisted Substrate grant")
})?;
let within_scope = authority.requested_paths.iter().all(|path| {
route.authorized_paths.iter().any(|scope| {
path == scope || path.starts_with(&format!("{}/", scope.trim_end_matches(['/', '\\'])))
})
});
if route.next_organ != RepoFrontierNextOrgan::Hands
|| authority.route_id != route.route_id
|| authority.model_projection_digest != route.model_projection_digest
|| authority.model_source_documents != route.model_source_documents
|| authority.frontier_item_id != route.frontier_item_id
|| authority.frontier_item_hash != route.frontier_item_hash
|| review.intent_id != intent.intent_id
|| review.decision != "approved"
|| intent.substrate_gate_grant_receipt_id != grant.receipt_id
|| grant.runtime_job_id != intent.runtime_job_id
|| grant.binding_id != intent.binding_id
|| grant.role != intent.role
|| grant.authority_scope != intent.authority_scope
|| authority.requested_paths != intent.requested_paths
|| authority.requested_paths != grant.granted_paths
|| !within_scope
{
return Err(anyhow!(
"repo frontier Hands authority does not exactly bind route, model, intent, review, grant, and scope"
));
}
let (envelope, _) = cache.prepare_entry(&authority.authority_id, authority)?;
let backing = SingleFileMessagePackBackingStore::new(store_path);
let expected = vec![
@ -7083,14 +6956,11 @@ pub fn put_repo_frontier_hands_authority(
cache
.get_envelope::<HandsActionIntent>(&intent.intent_id)?
.ok_or_else(|| anyhow!("repo frontier Hands authority lost its intent envelope"))?,
cache
.get_envelope::<HandsActionReview>(&review.review_id)?
.ok_or_else(|| anyhow!("repo frontier Hands authority lost its review envelope"))?,
cache
.get_envelope::<SubstrateGateRepoAccessGrantReceipt>(&grant.receipt_id)?
.ok_or_else(|| anyhow!("repo frontier Hands authority lost its grant envelope"))?,
cache
.get_envelope::<crate::EpiphanyRepoModelFrontierDocument>(&authority.frontier_item_id)?
.get_envelope::<crate::EpiphanyRepoModelFrontierDocument>(&route.frontier_item_id)?
.ok_or_else(|| anyhow!("repo frontier Hands authority lost its frontier envelope"))?,
];
let mut writes = expected.clone();
@ -7157,7 +7027,6 @@ pub(crate) fn validate_repo_frontier_verification_request_intrinsic(
request.frontier_item_id.as_str(),
request.frontier_item_hash.as_str(),
request.hands_intent_id.as_str(),
request.hands_review_id.as_str(),
request.hands_patch_receipt_id.as_str(),
request.hands_command_receipt_id.as_str(),
request.hands_commit_receipt_id.as_str(),
@ -7244,7 +7113,6 @@ fn repo_frontier_verification_context_with_commit(
.filter(|authority| {
authority.route_id == request.route_id
&& authority.hands_intent_id == request.hands_intent_id
&& authority.hands_review_id == request.hands_review_id
})
.collect::<Vec<_>>();
let [hands_authority] = authorities.as_slice() else {
@ -7256,9 +7124,6 @@ fn repo_frontier_verification_context_with_commit(
let hands_intent = cache
.get::<HandsActionIntent>(&request.hands_intent_id)?
.ok_or_else(|| anyhow!("Verification context lost its Hands intent"))?;
let hands_review = cache
.get::<HandsActionReview>(&request.hands_review_id)?
.ok_or_else(|| anyhow!("Verification context lost its Hands review"))?;
let patch_receipt = cache
.get::<HandsPatchReceipt>(&request.hands_patch_receipt_id)?
.ok_or_else(|| anyhow!("Verification context lost its patch receipt"))?;
@ -7268,8 +7133,7 @@ fn repo_frontier_verification_context_with_commit(
let commit_receipt = match prospective_commit {
Some(receipt)
if receipt.receipt_id == request.hands_commit_receipt_id
&& receipt.intent_id == request.hands_intent_id
&& receipt.review_id == request.hands_review_id =>
&& receipt.intent_id == request.hands_intent_id =>
{
receipt.clone()
}
@ -7288,7 +7152,6 @@ fn repo_frontier_verification_context_with_commit(
route,
hands_authority: hands_authority.clone(),
hands_intent,
hands_review,
patch_receipt,
command_receipt,
commit_receipt,
@ -7415,9 +7278,7 @@ fn derive_repo_frontier_verification_request_for_chain(
let authorities = cache
.get_all::<RepoFrontierHandsAuthority>()?
.into_iter()
.filter(|value| {
value.hands_intent_id == commit.intent_id && value.hands_review_id == commit.review_id
})
.filter(|value| value.hands_intent_id == commit.intent_id)
.collect::<Vec<_>>();
if authorities.len() != 1 {
return Err(anyhow!(
@ -7425,8 +7286,11 @@ fn derive_repo_frontier_verification_request_for_chain(
));
}
let authority = &authorities[0];
let route = cache
.get::<RepoFrontierRoute>(&authority.route_id)?
.ok_or_else(|| anyhow!("Hands authority lost its exact route"))?;
let frontier_envelope = cache
.get_envelope::<crate::EpiphanyRepoModelFrontierDocument>(&authority.frontier_item_id)?
.get_envelope::<crate::EpiphanyRepoModelFrontierDocument>(&route.frontier_item_id)?
.ok_or_else(|| anyhow!("Hands authority lost its exact frontier document"))?;
let frontier_authority_documents = vec![crate::EpiphanyMindDocumentVersion::from_envelope(
"epiphany-mind",
@ -7443,12 +7307,11 @@ fn derive_repo_frontier_verification_request_for_chain(
let request = RepoFrontierVerificationRequest {
request_id,
route_id: authority.route_id.clone(),
model_projection_digest: authority.model_projection_digest.clone(),
model_source_documents: authority.model_source_documents.clone(),
frontier_item_id: authority.frontier_item_id.clone(),
frontier_item_hash: authority.frontier_item_hash.clone(),
model_projection_digest: route.model_projection_digest.clone(),
model_source_documents: route.model_source_documents.clone(),
frontier_item_id: route.frontier_item_id.clone(),
frontier_item_hash: route.frontier_item_hash.clone(),
hands_intent_id: commit.intent_id.clone(),
hands_review_id: commit.review_id.clone(),
hands_patch_receipt_id: patch.receipt_id.clone(),
hands_command_receipt_id: command.receipt_id.clone(),
hands_commit_receipt_id: commit.receipt_id.clone(),
@ -7461,11 +7324,8 @@ fn derive_repo_frontier_verification_request_for_chain(
fn validate_hands_consequence_grant(
store_path: &Path,
intent_id: &str,
review_id: &str,
runtime_job_id: &str,
operation: &str,
changed_paths: &[String],
stated_grant_id: Option<&str>,
stated_command: Option<&str>,
) -> Result<()> {
let mut cache = runtime_spine_cache(store_path)?;
@ -7474,9 +7334,6 @@ fn validate_hands_consequence_grant(
let intent = cache
.get::<HandsActionIntent>(intent_id)?
.ok_or_else(|| anyhow!("Hands consequence requires its persisted intent"))?;
let review = cache
.get::<HandsActionReview>(review_id)?
.ok_or_else(|| anyhow!("Hands consequence requires its persisted review"))?;
let grant = cache
.get::<SubstrateGateRepoAccessGrantReceipt>(&intent.substrate_gate_grant_receipt_id)?
.ok_or_else(|| anyhow!("Hands consequence requires its persisted Substrate Gate grant"))?;
@ -7496,8 +7353,8 @@ fn validate_hands_consequence_grant(
.ok_or_else(|| anyhow!("Hands consequence requires its persisted repo frontier route"))?;
require_keyed_repo_model_basis(
&cache,
&authority.model_projection_digest,
&authority.model_source_documents,
&route.model_projection_digest,
&route.model_source_documents,
)?;
let paths_covered = changed_paths.iter().all(|path| {
grant.granted_paths.iter().any(|granted| {
@ -7506,22 +7363,11 @@ fn validate_hands_consequence_grant(
|| path.starts_with(&format!("{}/", granted.trim_end_matches(['/', '\\'])))
})
});
if intent.runtime_job_id != runtime_job_id
|| review.intent_id != intent.intent_id
|| review.decision != "approved"
|| !review
.allowed_operations
.iter()
.any(|allowed| allowed == operation)
|| grant.runtime_job_id != intent.runtime_job_id
|| grant.binding_id != intent.binding_id
|| grant.role != intent.role
|| grant.authority_scope != intent.authority_scope
if grant.runtime_job_id != intent.runtime_job_id
|| !grant
.granted_operations
.iter()
.any(|allowed| allowed == operation)
|| stated_grant_id.is_some_and(|id| id != grant.receipt_id)
|| stated_command.is_some_and(|command| {
route
.adopted_plan
@ -7529,23 +7375,19 @@ fn validate_hands_consequence_grant(
.is_some_and(|plan| command != plan.effective_command())
})
|| !paths_covered
|| authority.hands_review_id != review.review_id
|| authority.substrate_grant_receipt_id != grant.receipt_id
|| authority.requested_paths != intent.requested_paths
|| authority.route_id != route.route_id
|| authority.model_projection_digest != route.model_projection_digest
|| authority.model_source_documents != route.model_source_documents
|| authority.frontier_item_id != route.frontier_item_id
|| authority.frontier_item_hash != route.frontier_item_hash
|| authority.hands_intent_id != intent.intent_id
|| intent.requested_paths != route.authorized_paths
|| !changed_paths.iter().all(|path| {
authority.requested_paths.iter().any(|scope| {
intent.requested_paths.iter().any(|scope| {
path == scope
|| path.starts_with(&format!("{}/", scope.trim_end_matches(['/', '\\'])))
})
})
{
return Err(anyhow!(
"Hands consequence does not match its approved review and Substrate Gate grant"
"Hands consequence does not match its route, intent, and Substrate Gate grant"
));
}
Ok(())
@ -7558,12 +7400,6 @@ pub fn put_hands_patch_receipt(
let store_path = store_path.as_ref();
validate_non_empty(&receipt.receipt_id, "Hands patch receipt id")?;
validate_non_empty(&receipt.intent_id, "Hands patch intent")?;
validate_non_empty(&receipt.review_id, "Hands patch review")?;
validate_non_empty(
&receipt.substrate_gate_grant_receipt_id,
"Hands patch Substrate Gate grant receipt",
)?;
validate_non_empty(&receipt.runtime_job_id, "Hands patch runtime job")?;
validate_non_empty(&receipt.summary, "Hands patch summary")?;
validate_non_empty(&receipt.emitted_at, "Hands patch timestamp")?;
if receipt.changed_paths.is_empty() {
@ -7572,11 +7408,8 @@ pub fn put_hands_patch_receipt(
validate_hands_consequence_grant(
store_path.as_ref(),
&receipt.intent_id,
&receipt.review_id,
&receipt.runtime_job_id,
"patch",
&receipt.changed_paths,
Some(&receipt.substrate_gate_grant_receipt_id),
None,
)?;
let mut cache = runtime_spine_cache(store_path)?;
@ -7603,23 +7436,14 @@ pub fn put_hands_command_receipt(
let store_path = store_path.as_ref();
validate_non_empty(&receipt.receipt_id, "Hands command receipt id")?;
validate_non_empty(&receipt.intent_id, "Hands command intent")?;
validate_non_empty(&receipt.review_id, "Hands command review")?;
validate_non_empty(
&receipt.substrate_gate_grant_receipt_id,
"Hands command Substrate Gate grant receipt",
)?;
validate_non_empty(&receipt.runtime_job_id, "Hands command runtime job")?;
validate_non_empty(&receipt.command, "Hands command")?;
validate_non_empty(&receipt.exit_code, "Hands command exit code")?;
validate_non_empty(&receipt.emitted_at, "Hands command timestamp")?;
validate_hands_consequence_grant(
store_path.as_ref(),
&receipt.intent_id,
&receipt.review_id,
&receipt.runtime_job_id,
"command",
&[],
Some(&receipt.substrate_gate_grant_receipt_id),
Some(&receipt.command),
)?;
let mut cache = runtime_spine_cache(store_path)?;
@ -7646,8 +7470,6 @@ pub fn put_hands_commit_receipt(
let store_path = store_path.as_ref();
validate_non_empty(&receipt.receipt_id, "Hands commit receipt id")?;
validate_non_empty(&receipt.intent_id, "Hands commit intent")?;
validate_non_empty(&receipt.review_id, "Hands commit review")?;
validate_non_empty(&receipt.runtime_job_id, "Hands commit runtime job")?;
validate_non_empty(&receipt.commit_sha, "Hands commit sha")?;
validate_non_empty(&receipt.branch, "Hands commit branch")?;
validate_non_empty(&receipt.summary, "Hands commit summary")?;
@ -7658,41 +7480,33 @@ pub fn put_hands_commit_receipt(
validate_hands_consequence_grant(
store_path.as_ref(),
&receipt.intent_id,
&receipt.review_id,
&receipt.runtime_job_id,
"commit",
&receipt.changed_paths,
None,
None,
)?;
let mut cache = runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
require_identity(&cache)?;
let patch = cache
let patches = cache
.get_all::<HandsPatchReceipt>()?
.into_iter()
.filter(|patch| {
patch.intent_id == receipt.intent_id
&& patch.review_id == receipt.review_id
&& patch.runtime_job_id == receipt.runtime_job_id
&& patch.emitted_at <= receipt.emitted_at
})
.max_by(|left, right| left.emitted_at.cmp(&right.emitted_at))
.ok_or_else(|| anyhow!("Hands commit requires its exact patch receipt"))?;
let command = cache
.filter(|patch| patch.intent_id == receipt.intent_id)
.collect::<Vec<_>>();
let [patch] = patches.as_slice() else {
return Err(anyhow!("Hands commit requires one exact patch receipt"));
};
let commands = cache
.get_all::<HandsCommandReceipt>()?
.into_iter()
.filter(|command| {
command.intent_id == receipt.intent_id
&& command.review_id == receipt.review_id
&& command.runtime_job_id == receipt.runtime_job_id
&& command.exit_code == "0"
&& command.emitted_at <= receipt.emitted_at
})
.max_by(|left, right| left.emitted_at.cmp(&right.emitted_at))
.ok_or_else(|| anyhow!("Hands commit requires its successful command receipt"))?;
.filter(|command| command.intent_id == receipt.intent_id && command.exit_code == "0")
.collect::<Vec<_>>();
let [command] = commands.as_slice() else {
return Err(anyhow!(
"Hands commit requires one exact successful command receipt"
));
};
let request =
derive_repo_frontier_verification_request_for_chain(&cache, &patch, &command, receipt)?;
derive_repo_frontier_verification_request_for_chain(&cache, patch, command, receipt)?;
let context = repo_frontier_verification_context_with_commit(&cache, &request, Some(receipt))?;
let snapshot = cache.snapshot_envelopes();
let mut expected = Vec::new();
@ -7703,7 +7517,6 @@ pub fn put_hands_commit_receipt(
context.hands_authority.authority_id.as_str(),
),
(HandsActionIntent::TYPE, request.hands_intent_id.as_str()),
(HandsActionReview::TYPE, request.hands_review_id.as_str()),
(
HandsPatchReceipt::TYPE,
request.hands_patch_receipt_id.as_str(),

View file

@ -46,15 +46,13 @@ pub struct RepoFrontierVerificationRequest {
#[cultcache(key = 7)]
pub hands_intent_id: String,
#[cultcache(key = 8)]
pub hands_review_id: String,
#[cultcache(key = 9)]
pub hands_patch_receipt_id: String,
#[cultcache(key = 10)]
#[cultcache(key = 9)]
pub hands_command_receipt_id: String,
#[cultcache(key = 11)]
#[cultcache(key = 10)]
pub hands_commit_receipt_id: String,
#[cultcache(key = 12)]
#[cultcache(key = 11)]
pub requested_at: String,
#[cultcache(key = 14)]
#[cultcache(key = 12)]
pub frontier_authority_documents: Vec<crate::EpiphanyMindDocumentVersion>,
}

View file

@ -16,9 +16,9 @@ pub const REPO_FRONTIER_RESEARCH_CONTEXT_SCHEMA_VERSION: &str =
pub const REPO_FRONTIER_RESEARCH_CONTEXT_CONTRACT: &str =
"epiphany.repo_frontier_research_context.v3";
pub const REPO_FRONTIER_VERIFICATION_CONTEXT_SCHEMA_VERSION: &str =
"epiphany.worker.repo_frontier_verification_context.v1";
"epiphany.worker.repo_frontier_verification_context.v2";
pub const REPO_FRONTIER_VERIFICATION_CONTEXT_CONTRACT: &str =
"epiphany.repo_frontier_verification_context.v1";
"epiphany.repo_frontier_verification_context.v2";
pub const REPO_FRONTIER_PLAN_MIND_CONTEXT_SCHEMA_VERSION: &str =
"epiphany.worker.repo_frontier_plan_mind_context.v0";
pub const REPO_FRONTIER_PLAN_MIND_CONTEXT_CONTRACT: &str =
@ -241,7 +241,6 @@ pub struct RepoFrontierVerificationContextProjection {
pub route: crate::RepoFrontierRoute,
pub hands_authority: crate::RepoFrontierHandsAuthority,
pub hands_intent: crate::HandsActionIntent,
pub hands_review: crate::HandsActionReview,
pub patch_receipt: crate::HandsPatchReceipt,
pub command_receipt: crate::HandsCommandReceipt,
pub commit_receipt: crate::HandsCommitReceipt,

View file

@ -10,27 +10,27 @@ receipts that can be verified or admitted into Mind state.
- Inputs: typed action intents, Substrate Gate access grants, requested commands or
patches, current repo policy, Soul verification requirements, and coordinator
authority.
- Outputs: Hands action reviews, command receipts, patch receipts, commit
receipts, and action refusal receipts.
- Outputs: observed patch, command, and commit receipts.
- Derived state: diffs, command logs, and commits are action receipts. They are
not durable Mind state until Mind admits them.
- Forbidden writers: raw workers, Persona, Eyes, Imagination, Self, compatibility
JSON-RPC routes, and bridge tools must not execute repo-affecting commands,
edit files, commit, or publish without the Hands path after Body
access.
- Shared path: file edits, shell commands, and commits share Hands action
intent/review/receipt semantics.
- Shared path: file edits, shell commands, and commits share the exact adopted
route, action intent, Substrate Gate grant, frontier authority, and receipt
admission path.
- Deletion line: Substrate Gate grants access; it does not execute. Soul verifies; it
does not execute. Mind records durable state; it does not execute.
## Contract Families
- `epiphany.hands.action_intent`: request for bounded action.
- `epiphany.hands.action_review`: Hands decision and execution plan.
- `epiphany.hands.repo_frontier_authority`: exact binding among the adopted
route, action intent, and Substrate Gate grant.
- `epiphany.hands.command_receipt`: proof of command execution.
- `epiphany.hands.patch_receipt`: proof of file mutation.
- `epiphany.hands.commit_receipt`: proof of commit creation.
- `epiphany.hands.action_refusal_receipt`: proof that Hands refused to act.
## Neighboring Gates
@ -52,21 +52,28 @@ Epiphany may consume that provider-owned receipt after the local commit exists.
The first runtime-spine proof chain now exists:
```text
HandsActionIntent
-> HandsActionReview
RepoFrontierRoute + SubstrateGateRepoAccessGrantReceipt
-> HandsActionIntent + RepoFrontierHandsAuthority
-> HandsPatchReceipt
-> HandsCommandReceipt
-> HandsCommitReceipt
-> RepoFrontierVerificationRequest
```
`epiphany-core::hands_gateway` owns the typed document bodies and constructors.
`epiphany-core::runtime_spine` can persist and reread the intent, review, patch,
command, and commit receipts from the runtime-spine CultCache store.
The launch organ contract's repo-action proof profile now requires the full
Hands chain, not only the final patch receipt.
`epiphany-core::runtime_spine` admits the intent and consequence receipts into
the runtime-spine CultCache store and atomically creates Verification work with
the commit. The typed CultCache documents are the process boundary; public Rust
helper functions are not a substitute ABI.
`epiphany-mvp-coordinator` turns `continueImplementation` into a persisted
Substrate Gate grant plus Hands intent/review gate and exposes the exact receipt
identities required by downstream Verification.
Substrate Gate grant, Hands intent, and frontier authority, then exposes the
exact receipt families required by downstream Verification.
There is no separate Hands review document. The coordinator formerly authored
the grant, intent, review, and authority in one function, and the review could
only repeat `approved` plus the grant operations. It was a paper authority, not
an independent decision. Consequences now validate directly against the route,
intent, grant, and authority.
Epiphany currently has no admitted repository actuator. The former
`epiphany-hands-action` executable only accepted operator-authored descriptions