Prevent typed attempt resurrection

This commit is contained in:
Meta Vens 2026-08-10 12:04:13 +01:00
commit c693aaeadb
6 changed files with 260 additions and 46 deletions

View file

@ -21,7 +21,8 @@ use epiphany_core::{
retain_completed_runtime_sessions,
retain_coordinator_run_receipts, retain_resident_self_lifecycles,
settle_resident_self_exited_coordinator, terminate_process_instance,
validate_persona_feedback_store_separation, validate_resident_self_coordinator_receipt,
validate_persona_feedback_store_separation,
validate_resident_self_coordinator_receipt_binding,
validate_resident_self_store_separation, verify_resident_self_grant_fulfillment,
};
use serde_json::json;
@ -269,7 +270,7 @@ fn exact_resident_coordinator_receipt(
let Some(receipt) = receipts.pop() else {
return Ok(None);
};
validate_resident_self_coordinator_receipt(lease, &receipt)?;
validate_resident_self_coordinator_receipt_binding(lease, &receipt)?;
Ok(Some(receipt))
}
@ -447,12 +448,7 @@ fn cycle(
observation => {
let receipt =
exact_resident_coordinator_receipt(&args.policy.runtime_store, &lease)?;
if let Some(receipt) = receipt.as_ref().filter(|receipt| {
matches!(
receipt.status.as_str(),
"planned" | "needsReview" | "completed"
)
}) {
if let Some(receipt) = receipt.as_ref() {
let outcome = settle_resident_self_exited_coordinator(
&args.state_store,
&args.policy.runtime_store,
@ -467,26 +463,15 @@ fn cycle(
*state = load_resident_self_state(&args.state_store)?;
return Ok(outcome);
}
let outcome = if receipt.is_some() {
cancel_resident_self_turn(
&args.state_store,
&lease,
cancelled_turn_status(shutdown_requested, brake_engaged, timed_out),
"exact coordinator terminal receipt reports failure",
now,
)?;
outcome_after_cancel(shutdown_requested)
} else {
settle_receipt_free_dead_coordinator(
args,
&lease,
observation,
shutdown_requested,
brake_engaged,
timed_out,
now,
)?
};
let outcome = settle_receipt_free_dead_coordinator(
args,
&lease,
observation,
shutdown_requested,
brake_engaged,
timed_out,
now,
)?;
*state = load_resident_self_state(&args.state_store)?;
Ok(outcome)
}

View file

@ -1302,9 +1302,44 @@ pub fn settle_resident_self_exited_coordinator(
now_millis: u64,
cooldown_seconds: u64,
) -> Result<ResidentSelfOutcome> {
validate_resident_self_coordinator_receipt_binding(lease, receipt)?;
let typed = resident_self_grant_has_typed_request(resident_store, &lease.grant_id)?;
let typed_attempt = typed
&& resident_self_typed_attempt_exists(resident_store, runtime_store, &lease.grant_id)?;
let successful_receipt = matches!(
receipt.status.as_str(),
"planned" | "needsReview" | "completed"
);
if !typed
&& !successful_receipt
{
cancel_resident_self_turn(
resident_store,
lease,
if shutdown_requested {
"shutdown-cancelled"
} else if brake_engaged {
"brake-cancelled"
} else if timed_out {
"timed-out"
} else {
"process-failed"
},
"exact coordinator terminal receipt reports failure",
now_millis,
)?;
return Ok(if shutdown_requested {
ResidentSelfOutcome::Braked
} else {
ResidentSelfOutcome::Failed
});
}
match verify_resident_self_grant_fulfillment(resident_store, runtime_store, &lease.grant_id) {
Ok(ResidentSelfGrantFulfillment::Pending)
if !(shutdown_requested || brake_engaged || timed_out) =>
if typed
&& (typed_attempt
|| (successful_receipt
&& !(shutdown_requested || brake_engaged || timed_out))) =>
{
Ok(ResidentSelfOutcome::AwaitingFulfillment)
}
@ -1332,22 +1367,36 @@ pub fn settle_resident_self_exited_coordinator(
})
}
Err(error) => {
cancel_resident_self_turn(
resident_store,
lease,
"unfulfilled",
&error.to_string(),
now_millis,
)?;
if typed_attempt {
complete_resident_self_turn_with_terminal(
resident_store,
lease,
&format!("resident-self-runtime-unfulfilled-{}", lease.grant_id),
"unfulfilled",
now_millis,
cooldown_seconds,
true,
)?;
} else {
cancel_resident_self_turn(
resident_store,
lease,
"unfulfilled",
&error.to_string(),
now_millis,
)?;
}
Ok(ResidentSelfOutcome::Failed)
}
Ok(ResidentSelfGrantFulfillment::Fulfilled) => {
complete_resident_self_turn(
complete_resident_self_turn_with_terminal(
resident_store,
lease,
receipt,
&receipt.receipt_id,
&receipt.status,
now_millis,
cooldown_seconds,
false,
)?;
Ok(ResidentSelfOutcome::Completed)
}
@ -1773,6 +1822,7 @@ pub fn resident_self_child_claim(
.get::<ResidentSelfChildClaim>(&format!("resident-self-child-claim-{preparation_id}"))
}
#[cfg(test)]
fn complete_resident_self_turn(
path: &Path,
lease: &ResidentSelfTurnLease,
@ -1788,20 +1838,33 @@ fn complete_resident_self_turn(
&coordinator.status,
now_millis,
cooldown_seconds,
false,
)
}
pub fn validate_resident_self_coordinator_receipt(
lease: &ResidentSelfTurnLease,
coordinator: &crate::EpiphanyCoordinatorRunReceipt,
) -> Result<()> {
validate_resident_self_coordinator_receipt_binding(lease, coordinator)?;
if !matches!(
coordinator.status.as_str(),
"planned" | "needsReview" | "completed"
) {
return Err(anyhow!(
"coordinator terminal receipt is not successful"
));
}
Ok(())
}
pub fn validate_resident_self_coordinator_receipt_binding(
lease: &ResidentSelfTurnLease,
coordinator: &crate::EpiphanyCoordinatorRunReceipt,
) -> Result<()> {
if coordinator.thread_id != lease.turn_id
|| coordinator.session_id
!= crate::coordinator_run_session_id(&lease.turn_id, Some(&lease.launch_digest))?
|| !matches!(
coordinator.status.as_str(),
"planned" | "needsReview" | "completed"
)
|| coordinator.resident_grant_id.as_deref() != Some(&lease.grant_id)
|| coordinator.resident_launch_digest.as_deref() != Some(&lease.launch_digest)
|| coordinator.resident_policy_digest.as_deref() != Some(&lease.policy_digest)
@ -1848,6 +1911,7 @@ pub fn complete_resident_self_turn_after_death(
"recovered-fulfilled",
now_millis,
cooldown_seconds,
false,
)
}
@ -1858,6 +1922,7 @@ fn complete_resident_self_turn_with_terminal(
terminal_status: &str,
now_millis: u64,
cooldown_seconds: u64,
count_failure: bool,
) -> Result<ResidentSelfTerminalAck> {
let cache = state_cache(path)?;
let mut state = cache
@ -1905,6 +1970,7 @@ fn complete_resident_self_turn_with_terminal(
state.last_coordinator_receipt_id = Some(terminal_id.to_string());
state.next_eligible_at_millis =
now_millis.saturating_add(cooldown_seconds.saturating_mul(1000));
state.consecutive_failures += u64::from(count_failure);
state.revision += 1;
grant.schema_version = RESIDENT_SELF_GRANT_SCHEMA_VERSION.into();
grant.terminal_at_millis = Some(now_millis);
@ -3124,6 +3190,13 @@ mod tests {
let mut wrong_session = receipt.clone();
wrong_session.session_id = format!("{}-substituted", receipt.session_id);
assert!(validate_resident_self_coordinator_receipt(&lease, &wrong_session).is_err());
let mut bound_failure = receipt.clone();
bound_failure.status = "failed".into();
assert!(
validate_resident_self_coordinator_receipt_binding(&lease, &bound_failure).is_ok(),
"terminal status does not decide whether a receipt belongs to the lease"
);
assert!(validate_resident_self_coordinator_receipt(&lease, &bound_failure).is_err());
assert_eq!(
settle_resident_self_exited_coordinator(
&store,
@ -3663,6 +3736,95 @@ mod tests {
assert_eq!(retry_grant.pressure_id, first_grant.pressure_id);
assert_ne!(retry_grant.grant_id, first_grant.grant_id);
assert!(retry_grant.grant_id.contains("-attempt-2-"));
let prepared = prepare_resident_self_launch(&store, &policy, 9)?.expect("retry preparation");
let retry_process = LaunchedCoordinator {
process_id: 45,
process_creation_token: 56,
process_executable_path: process.process_executable_path.clone(),
};
claim_resident_self_preparation_as_child(
&store,
&prepared.preparation_id,
&retry_process,
10,
)?;
let retry_lease = acknowledge_resident_self_launch(
&store,
&prepared.preparation_id,
&retry_process,
11,
)?;
let mut runtime = crate::runtime_spine_cache(&policy.runtime_store)?;
runtime.pull_all_backing_stores()?;
let request = runtime
.get::<crate::AdmittedModelDirectionConsiderationRequest>("request-retry-1")?
.expect("retry request");
let result = crate::AdmittedModelDirectionConsiderationResult {
schema_version: crate::ADMITTED_MODEL_DIRECTION_CONSIDERATION_RESULT_SCHEMA_VERSION
.into(),
result_id: crate::admitted_model_direction_consideration_result_id_for_launch(
&request.request_id,
"job-retry-hostile",
),
request_id: request.request_id.clone(),
runtime_id: request.runtime_id.clone(),
thread_id: request.thread_id.clone(),
model_revision: request.model_revision,
model_hash: request.model_hash.clone(),
model_admission_receipt_id: request.model_admission_receipt_id.clone(),
disposition: crate::AdmittedModelDirectionDisposition::Hold,
summary: "Hostile terminal claimant fixture.".into(),
option_drafts: vec![],
uncertainties: vec![],
evidence_refs: vec![request.model_admission_receipt_id.clone()],
proposed_at: "2026-07-18T00:00:01Z".into(),
contract: crate::ADMITTED_MODEL_DIRECTION_CONSIDERATION_RESULT_CONTRACT.into(),
proposal_only: true,
terminal: true,
};
admit_test_model_direction_result(
&policy.runtime_store,
&request,
&result,
"job-retry-hostile",
)?;
let mut hostile = crate::runtime_role_worker_result(
&policy.runtime_store,
"job-retry-hostile",
)?
.expect("persisted worker result");
hostile.item_error = Some("terminal typed output failed validation".into());
let mut runtime = crate::runtime_spine_cache(&policy.runtime_store)?;
runtime.put("job-retry-hostile", &hostile)?;
let mut receipt = coordinator_receipt_for_lease(&retry_lease, &policy.runtime_store);
receipt.status = "failed".into();
assert_eq!(
settle_resident_self_exited_coordinator(
&store,
&policy.runtime_store,
&retry_lease,
&receipt,
false,
false,
false,
12,
policy.cooldown_seconds,
)?,
ResidentSelfOutcome::Failed
);
let pressure = state_cache(&store)?
.get::<ResidentSelfPressure>("pressure-retry-1")?
.expect("terminal attempted pressure");
assert_eq!(pressure.status, "consumed");
assert_eq!(
pressure.consumed_by_grant_id.as_deref(),
Some(retry_grant.grant_id.as_str())
);
assert!(
heartbeat_issue_resident_self_grant(&store, "heartbeat-3", "action-3", 13)?.is_none(),
"a hostile terminal typed claimant cannot resurrect its request as another grant"
);
Ok(())
}

View file

@ -3083,3 +3083,29 @@ that entire namespace and then write a terminal receipt. Backend failure leaves
the obligation pending and cannot affect readiness. The logical retention owner
must preserve attempted lifecycle until that obligation exists; a cumulative
digest is evidence, not a retry address.
### Typed attempts own retry eligibility
The c006 live run exposed a split between typed runtime authority and resident
cancellation. A coordinator process receipt owns process closure, but it does
not own whether a typed request may launch again. The immutable typed launch
and runtime-owned fulfillment chain own that decision.
- Receipt binding is structural: exact session incarnation, thread, grant,
launch, policy, argv, objective, release, and executable digests. Terminal
status is classified only after that binding succeeds.
- A successful coordinator receipt with no observed attempt may briefly retain
the active lease while asynchronous typed publication arrives.
- Once an exact typed attempt exists, missing terminal fulfillment remains
`awaiting-fulfillment`, including across brake, shutdown, or timeout. Those
signals cannot manufacture supersession.
- A hostile terminal typed claimant closes the exact resident grant as
`unfulfilled` and leaves its pressure consumed. It cannot become another
Heartbeat grant.
- Generic cancellation may return a typed pressure to Heartbeat only when no
immutable typed attempt exists. Explicit runtime-owned supersession remains
the sole route to a later attempt.
The negative verification is the c006 failure shape itself: a fully bound
`failed` coordinator receipt plus an invalid terminal proposal Modeling result
must settle once, must not crash resident Self, and must not issue attempt
three. Exact live replay remains the package acceptance boundary.

View file

@ -1,5 +1,46 @@
# Fresh workspace handoff
## c006 live scheduling exposed typed retry resurrection — 2026-08-10
Exact pushed source `8d92c8266b07a98b5c6b2e8d6bdbded5661e8cbb` packaged
without warnings as 24-binary release
`sha256-e0f5b6084ea779dd0a7e22536b2cf371c0579b8ab06e52f728ddc8912caf2dab`
with witness
`sha256-8a8833b7a501a774173debe6b93658f1885691b3f35a1c7534e907d26d8860ea`.
The integrated copied-state negative proved that resident Heartbeat observes
the mounted cognitive brake namespace even when release identity differs.
On actual c006, Heartbeat consumed the historical terminal acknowledgement
without reissuing either old grant. The first admitted-model-direction grant
completed exactly once. Proposal Modeling then completed one valid request and
advanced to another. That later worker persisted an immutable launch and a
terminal result which failed runtime fulfillment validation. Resident Self
cancelled and requeued the same typed request; Heartbeat issued attempt two;
the coordinator correctly refused it because attempt one's launch remained
unsuperseded. The resulting fully bound `failed` coordinator receipt then
crashed resident settlement because the receipt lookup incorrectly used the
success-only validator before status classification.
The cognitive brake is engaged on
`epiphany-starfire-linux-eyes-tools`. Both c006 processes are stopped. Heartbeat
still lacks graceful SIGTERM and stopped with exit 137 after observing the
brake. Exact copied stores, container inspection, and logs are preserved under
`.epiphany-run/interventions/c006-unsuperseded-relaunch-20260810T1044Z/`.
Do not release the brake or restart c006 from `8d92c826`.
Current source moves both decisions to their owners. Receipt binding is checked
independently of terminal success, so a fully bound failed receipt reaches
settlement. Once a typed attempt exists, pending work retains the active lease
and hostile terminal output closes the exact grant as unfulfilled without
returning its pressure to Heartbeat. Generic cancellation may requeue only
before a typed attempt exists. The live-shaped regression proves a bound failed
receipt plus hostile terminal claimant cannot mint attempt three. The full core
suite passes 654 tests with one intentional ignore; nine swarm binary tests and
warning-free lib/swarm checks pass. Commit/package this cut once, then replay
against a copy of the sealed c006 failure state. Require exact settlement,
consumed pressure, no new grant, parseable stores, and clean resident restart
under the cognitive brake before touching actual c006.
## c006 recovery exposed Heartbeat identity and legacy-session residue — 2026-08-10
Exact `9bf985fc4ab5a7f75de26493ed6e122524c71775` packaged in 6m46s as

Binary file not shown.

View file

@ -36,9 +36,9 @@ invariants:
current_status:
summary: Epiphany is a supervised engineering alpha on Starfire, not deployment-ready. Exact b8138a6b active-child SIGTERM and restart, exact 9f369528 deterministic warm packaging, exact c930f505 cross-container ownership, exact ed15f83a resident lifecycle retention, exact 16c4b19f coordinator receipt and Heartbeat artifact retention, exact cce2b8ac narrow model-generation retention, exact eea15e82 model-turn JSON ingress, exact b1e8c89a semantic unattempted-generation retention, exact 6bc3ec3f semantic physical-epoch retirement, and exact 44230a05 Persona conversation retention are proven. Gamecult-ops 059821f owns Yggdrasil stream retention and exact 6ee08a4 owns stable Starfire Persona-permit firewall ingress. Exact 16c4b19f genuine idle and exact a987d2f7 active cognition completed 900-pulse bounded plateaus. Runtime-owned typed fulfillment is accepted live under exact 6dd9b132. Yggdrasil is the small public crossing body, never the release forge.
latest_phase: Exact 9bf985fc packages crash-atomic storage plus resident/readiness cognitive identity as warning-free 24-binary release sha256-eedde4e6 with witness sha256-828949cd. c006 recovery refused an unbound legacy family that reused one active session across 24 starts and 22 receipts. Timestamp inference was rejected as unsound; the whole family was quarantined under a full-snapshot fence with exact pre-state and typed external receipt preserved. c006 then ran sleeping and stopped SIGTERM exit 0. No pulse was allowed because packaged Heartbeat still selected release identity for its brake. Current source requires resident-runtime-store and resolves mounted cognition for the scheduling brake; four Heartbeat tests pass with deliberate differing identities. The named volume retains two terminal historical grants and one typed pending model-direction pressure without the zero file. Commit and package the Heartbeat cut before waking scheduling.
latest_phase: Exact 8d92c826 packages the cognitive Heartbeat brake cut as warning-free 24-binary release sha256-e0f5b608 with witness sha256-8a8833b7. Actual c006 consumed historical acknowledgement without old-grant resurrection and completed the first typed model-direction lifecycle. Continued scheduling exposed a typed retry resurrection: invalid terminal proposal Modeling output was generically requeued despite its immutable launch, attempt two correctly refused the unsuperseded launch, and resident Self then crashed because failed receipt binding was prefiltered through a success-only validator. The cognitive brake is engaged and both c006 processes are stopped; exact stores/logs are sealed. Current source separates receipt ownership from success and prevents an attempted typed request from returning to Heartbeat. Full core verification passes 654 with one intentional ignore. Commit/package once and replay only on copied c006 failure state.
operational_state:
local_worktree: heartbeat_cognitive_brake_cut_source_verified_pending_commit
local_worktree: typed_attempt_non_resurrection_cut_source_verified_pending_commit
operator_wireguard: restored
starfire_persona_permit_firewall: persistent_exact_gamecult_ops_6ee08a4
yggdrasil: canonical_small_public_crossing_body
@ -68,9 +68,9 @@ current_status:
starfire_linux_role_cognition: eyes_and_modeling_tools_results_and_acceptance_proven_zero_consequence
starfire_linux_modeling_peak: 109887488_bytes_resident_body_plus_modeling_circuit
yggdrasil_epiphany_service_contract: repaired_in_gamecult_ops_812b427_not_installed
resident_physiology: c005_exited_255_and_sealed_as_corruption_evidence
resident_physiology: c006_braked_and_stopped_after_bound_failed_receipt_exposed_typed_retry_resurrection
unresolved_authority: Coordinator receipt, Heartbeat pulse-artifact, deployed supervisor/projector log retention, genuine-idle and active resource plateaus, exact-grant terminality, restart-persistent cooldown refusal, schedule/action issuance cardinality, runtime-owned typed fulfillment, narrow model-generation retention, published model-turn JSON ingress, semantic logical/physical retention, Persona conversation retention, stable Starfire firewall ownership, completed model-adapter session archival, and normal coordinator lifecycle opening/error closure/legacy repair/archival are accepted live. Receipt-free hard-death recovery is source- and package-accepted but its live kill matrix remains unproven because the first copied run exposed non-atomic storage publication. A typed worker launch without valid terminal fulfillment deliberately remains active awaiting an owner for exact orphan-worker death and supersession; it is not retryable yet. Historical migrated semantic attempts without recorded physical namespace remain durable and non-retirable. Repository Body observation still performs two authenticated full-tree Git index/manifest passes. Execute-mode workers require a persistent process body. Mutable Starfire bind storage is not accepted as resident authority until the packaged CultCache repair and recovery replay pass. One completed Discord consequence remains blocked by the absent Yggdrasil credential.
next_action: Commit and push the Heartbeat cognitive-brake cut, package once with the persistent Starfire cache, and publish it into c006. Start exact resident Self plus Heartbeat with the mounted runtime store. Require Heartbeat to consume the historical terminal acknowledgement without reissuing either old grant, issue one new grant for the sole pending typed pressure, complete it once, and pass SIGTERM/restart plus parseable-store checks. Then resume copied receipt-free death and orphan-worker Continuity. Yggdrasil never builds.
next_action: Commit and push the typed-attempt non-resurrection and failed-receipt binding cut, package once with the persistent Starfire cache, and replay it only against a copy of the sealed c006 failure stores. Require the exact active attempt-two lease to settle without resident crash, keep the attempted pressure consumed, issue no attempt three under cognitive brake, preserve parseable stores, and restart resident cleanly braked. Then decide whether actual c006 needs an evidence-grounded state intervention before release, cut Heartbeat graceful SIGTERM, and resume copied receipt-free death/orphan-worker Continuity. Yggdrasil never builds.
active_subgoals:
- Prove Persona, Self, Eyes, Modeling, Imagination, Hands, Soul, Mind, Continuity, and nervous-system behavior individually.