diff --git a/epiphany-core/src/resident_self.rs b/epiphany-core/src/resident_self.rs index 551ca8b7..6485f563 100644 --- a/epiphany-core/src/resident_self.rs +++ b/epiphany-core/src/resident_self.rs @@ -12,7 +12,7 @@ pub const RESIDENT_SELF_STATE_SCHEMA_VERSION: &str = "epiphany.resident_self.sta pub const RESIDENT_SELF_RUNTIME_RECEIPT_SCHEMA_VERSION: &str = "epiphany.resident_self.runtime_receipt.v0"; pub const RESIDENT_SELF_PRESSURE_SCHEMA_VERSION: &str = "epiphany.resident_self.pressure.v0"; -pub const RESIDENT_SELF_GRANT_SCHEMA_VERSION: &str = "epiphany.resident_self.heartbeat_grant.v0"; +pub const RESIDENT_SELF_GRANT_SCHEMA_VERSION: &str = "epiphany.resident_self.heartbeat_grant.v1"; pub const RESIDENT_SELF_ACK_SCHEMA_VERSION: &str = "epiphany.resident_self.terminal_ack.v0"; pub const RESIDENT_SELF_CHILD_CLAIM_SCHEMA_VERSION: &str = "epiphany.resident_self.child_claim.v0"; pub const RESIDENT_SELF_RETENTION_HEAD_SCHEMA_VERSION: &str = @@ -108,6 +108,10 @@ pub struct ResidentSelfHeartbeatGrant { pub consumed_at_millis: Option, #[cultcache(key = 10, default)] pub private_state_exposed: bool, + #[cultcache(key = 11, default)] + pub terminal_at_millis: Option, + #[cultcache(key = 12, default)] + pub terminal_status: Option, } #[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)] @@ -1096,7 +1100,7 @@ pub fn heartbeat_issue_resident_self_grant( if state.active_turn.is_some() || state.prepared_launch.is_some() { return Ok(None); } - let terminal_grant_ids = cache + let legacy_terminal_grant_ids = cache .get_all::()? .into_iter() .map(|ack| ack.grant_id) @@ -1104,7 +1108,10 @@ pub fn heartbeat_issue_resident_self_grant( let grants = cache.get_all::()?; if grants.iter().any(|grant| { (grant.heartbeat_schedule_id == schedule_id && grant.heartbeat_action_id == action_id) - || (grant.consumed_at_millis.is_none() && !terminal_grant_ids.contains(&grant.grant_id)) + || (grant.consumed_at_millis.is_none() + && grant.terminal_at_millis.is_none() + && !(grant.schema_version == "epiphany.resident_self.heartbeat_grant.v0" + && legacy_terminal_grant_ids.contains(&grant.grant_id))) }) { return Ok(None); } @@ -1142,6 +1149,8 @@ pub fn heartbeat_issue_resident_self_grant( issued_at_millis: now_millis, consumed_at_millis: None, private_state_exposed: false, + terminal_at_millis: None, + terminal_status: None, }; let snapshot = cache.snapshot_envelopes(); let expected_pressure = snapshot @@ -1357,7 +1366,7 @@ pub fn settle_resident_self_exited_coordinator( pub fn pending_resident_self_grant(path: &Path) -> Result> { let cache = state_cache(path)?; - let terminal_grant_ids = cache + let legacy_terminal_grant_ids = cache .get_all::()? .into_iter() .map(|ack| ack.grant_id) @@ -1366,7 +1375,10 @@ pub fn pending_resident_self_grant(path: &Path) -> Result()? .into_iter() .filter(|grant| { - grant.consumed_at_millis.is_none() && !terminal_grant_ids.contains(&grant.grant_id) + grant.consumed_at_millis.is_none() + && grant.terminal_at_millis.is_none() + && !(grant.schema_version == "epiphany.resident_self.heartbeat_grant.v0" + && legacy_terminal_grant_ids.contains(&grant.grant_id)) }) .collect::>(); grants.sort_by(|a, b| { @@ -1689,15 +1701,15 @@ fn complete_resident_self_turn( "resident Self active lease changed before terminal ack" )); } - let grant = cache + let mut grant = cache .get::(&lease.grant_id)? .ok_or_else(|| anyhow!("resident Self grant missing at terminal ack"))?; let ack = ResidentSelfTerminalAck { schema_version: RESIDENT_SELF_ACK_SCHEMA_VERSION.into(), ack_id: format!("resident-self-ack-{}", lease.grant_id), grant_id: lease.grant_id.clone(), - heartbeat_schedule_id: grant.heartbeat_schedule_id, - heartbeat_action_id: grant.heartbeat_action_id, + heartbeat_schedule_id: grant.heartbeat_schedule_id.clone(), + heartbeat_action_id: grant.heartbeat_action_id.clone(), launch_digest: lease.launch_digest.clone(), coordinator_receipt_id: coordinator.receipt_id.clone(), terminal_status: coordinator.status.clone(), @@ -1705,24 +1717,38 @@ fn complete_resident_self_turn( consumed_by_heartbeat_at_millis: None, private_state_exposed: false, }; - let expected = cache - .snapshot_envelopes() - .into_iter() + let envelopes = cache.snapshot_envelopes(); + let expected_state = envelopes + .iter() .find(|entry| { entry.r#type == ::TYPE && entry.key == RESIDENT_SELF_STATE_KEY }) + .cloned() .ok_or_else(|| anyhow!("resident Self state lost envelope"))?; + let expected_grant = envelopes + .iter() + .find(|entry| { + entry.r#type == ::TYPE + && entry.key == grant.grant_id + }) + .cloned() + .ok_or_else(|| anyhow!("resident Self grant lost envelope at terminal ack"))?; state.active_turn = None; state.last_coordinator_receipt_id = Some(coordinator.receipt_id.clone()); state.next_eligible_at_millis = now_millis.saturating_add(cooldown_seconds.saturating_mul(1000)); state.revision += 1; + grant.schema_version = RESIDENT_SELF_GRANT_SCHEMA_VERSION.into(); + grant.terminal_at_millis = Some(now_millis); + grant.terminal_status = Some(coordinator.status.clone()); let (state_entry, _) = cache.prepare_entry(RESIDENT_SELF_STATE_KEY, &state)?; + let (grant_entry, _) = cache.prepare_entry(&grant.grant_id, &grant)?; let (ack_entry, _) = cache.prepare_entry(&ack.ack_id, &ack)?; - if !SingleFileMessagePackBackingStore::new(path) - .compare_and_swap_batch(&[expected], vec![state_entry, ack_entry])? - { + if !SingleFileMessagePackBackingStore::new(path).compare_and_swap_batch( + &[expected_state, expected_grant], + vec![state_entry, grant_entry, ack_entry], + )? { return Err(anyhow!("resident Self lost terminal-ack CAS")); } Ok(ack) @@ -1751,7 +1777,7 @@ pub fn cancel_resident_self_turn( if state.active_turn.as_ref() != Some(lease) { return Err(anyhow!("resident Self cancellation lease changed")); } - let grant = cache + let mut grant = cache .get::(&lease.grant_id)? .ok_or_else(|| anyhow!("resident Self cancellation grant missing"))?; let mut pressure = cache @@ -1768,8 +1794,8 @@ pub fn cancel_resident_self_turn( schema_version: RESIDENT_SELF_ACK_SCHEMA_VERSION.into(), ack_id: format!("resident-self-cancel-{}-{status}", lease.grant_id), grant_id: lease.grant_id.clone(), - heartbeat_schedule_id: grant.heartbeat_schedule_id, - heartbeat_action_id: grant.heartbeat_action_id, + heartbeat_schedule_id: grant.heartbeat_schedule_id.clone(), + heartbeat_action_id: grant.heartbeat_action_id.clone(), launch_digest: lease.launch_digest.clone(), coordinator_receipt_id: format!("resident-self-runtime-{status}-{}", lease.grant_id), terminal_status: status.into(), @@ -1794,18 +1820,30 @@ pub fn cancel_resident_self_turn( }) .cloned() .ok_or_else(|| anyhow!("resident Self cancellation pressure envelope missing"))?; + let expected_grant = envelopes + .iter() + .find(|entry| { + entry.r#type == ::TYPE + && entry.key == grant.grant_id + }) + .cloned() + .ok_or_else(|| anyhow!("resident Self cancellation grant envelope missing"))?; state.active_turn = None; state.revision += 1; state.consecutive_failures += u64::from(!matches!(status, "brake-cancelled" | "shutdown-cancelled")); pressure.status = "pending".into(); pressure.consumed_by_grant_id = None; + grant.schema_version = RESIDENT_SELF_GRANT_SCHEMA_VERSION.into(); + grant.terminal_at_millis = Some(now_millis); + grant.terminal_status = Some(status.into()); let (state_entry, _) = cache.prepare_entry(RESIDENT_SELF_STATE_KEY, &state)?; let (pressure_entry, _) = cache.prepare_entry(&pressure.pressure_id, &pressure)?; + let (grant_entry, _) = cache.prepare_entry(&grant.grant_id, &grant)?; let (ack_entry, _) = cache.prepare_entry(&ack.ack_id, &ack)?; if !SingleFileMessagePackBackingStore::new(path).compare_and_swap_batch( - &[expected_state, expected_pressure], - vec![state_entry, pressure_entry, ack_entry], + &[expected_state, expected_pressure, expected_grant], + vec![state_entry, pressure_entry, grant_entry, ack_entry], )? { return Err(anyhow!("resident Self lost cancellation CAS")); } @@ -1890,6 +1928,12 @@ pub fn retain_resident_self_lifecycles( .filter_map(|ack| { let grant = grants.get(&ack.grant_id)?; let pressure = pressures.get(&grant.pressure_id)?; + let terminal_grant = if grant.schema_version == RESIDENT_SELF_GRANT_SCHEMA_VERSION { + grant.terminal_at_millis == Some(ack.completed_at_millis) + && grant.terminal_status.as_deref() == Some(ack.terminal_status.as_str()) + } else { + grant.schema_version == "epiphany.resident_self.heartbeat_grant.v0" + }; let inactive = state.active_turn.as_ref().map(|lease| &lease.grant_id) != Some(&grant.grant_id) && state @@ -1899,6 +1943,7 @@ pub fn retain_resident_self_lifecycles( != Some(&grant.grant_id); (ack.consumed_by_heartbeat_at_millis.is_some() && grant.consumed_at_millis.is_some() + && terminal_grant && pressure.status == "consumed" && pressure.consumed_by_grant_id.as_deref() == Some(grant.grant_id.as_str()) && inactive) @@ -2055,6 +2100,8 @@ mod tests { issued_at_millis: completed_at_millis.saturating_sub(2), consumed_at_millis: Some(completed_at_millis.saturating_sub(1)), private_state_exposed: false, + terminal_at_millis: Some(completed_at_millis), + terminal_status: Some("completed".into()), }; let ack = ResidentSelfTerminalAck { schema_version: RESIDENT_SELF_ACK_SCHEMA_VERSION.into(), @@ -2777,6 +2824,8 @@ mod tests { let mut stale_grant = cache .get::(&grant.grant_id)? .expect("completed grant"); + assert_eq!(stale_grant.terminal_at_millis, Some(10)); + assert_eq!(stale_grant.terminal_status.as_deref(), Some("planned")); let expected_grant = cache .snapshot_envelopes() .into_iter() @@ -2792,9 +2841,21 @@ mod tests { .compare_and_swap_entry(&expected_grant, stale_entry)?, "test must install the observed restart-corruption shape" ); + let ack_envelope = state_cache(&store)? + .snapshot_envelopes() + .into_iter() + .find(|entry| { + entry.r#type == ResidentSelfTerminalAck::TYPE && entry.key == acks[0].ack_id + }) + .expect("terminal acknowledgement envelope"); + assert!( + SingleFileMessagePackBackingStore::new(&store) + .delete_batch_if_unchanged(&[ack_envelope])?, + "test must install the observed missing-ack shape" + ); assert!( pending_resident_self_grant(&store)?.is_none(), - "terminal acknowledgement permanently kills its exact grant" + "the exact grant's terminal state permanently kills its launch authority" ); assert!(prepare_resident_self_launch(&store, &policy, 10_010)?.is_none()); let later_pressure = ResidentSelfPressure { @@ -3183,7 +3244,15 @@ mod tests { assert_eq!(pressure.consumed_by_grant_id, None); assert!( heartbeat_issue_resident_self_grant(&store, "heartbeat-1", "action-1", 7)?.is_none(), - "a terminal acknowledgement ends grant authority for its Heartbeat turn" + "a terminal grant ends authority for its Heartbeat turn" + ); + let terminal_grant = state_cache(&store)? + .get::(&first_grant.grant_id)? + .expect("terminal first grant"); + assert_eq!(terminal_grant.terminal_at_millis, Some(6)); + assert_eq!( + terminal_grant.terminal_status.as_deref(), + Some("unfulfilled") ); let retry_grant = heartbeat_issue_resident_self_grant(&store, "heartbeat-2", "action-2", 8)? diff --git a/notes/epiphany-current-algorithmic-map.md b/notes/epiphany-current-algorithmic-map.md index 3f13e483..aba56681 100644 --- a/notes/epiphany-current-algorithmic-map.md +++ b/notes/epiphany-current-algorithmic-map.md @@ -1380,14 +1380,16 @@ Heartbeat turn. Pressure arriving after that turn spent its grant stays pending until Heartbeat consumes the exact terminal acknowledgement and schedules a different coordinator turn. -Terminal acknowledgement is irreversible grant death. Pending-grant selection -loads all `ResidentSelfTerminalAck` rows first and excludes their exact grant IDs -before considering `consumed_at_millis`. Heartbeat applies the same exclusion -when deciding whether another unconsumed grant blocks issuance. The consumed -marker proves preparation consumed launch authority; it cannot reopen authority -after completion, cancellation, restart, stale-envelope resolution, or marker -regression. Lifecycle retention may delete this evidence only after Heartbeat has -consumed the acknowledgement and the owning turn is already closed. +Each `ResidentSelfHeartbeatGrant` owns its irreversible terminality. Completion +and cancellation write the exact grant's terminal timestamp and status in the +same snapshot-fenced CAS that clears its active lease. Pending-grant selection +and Heartbeat issuance read that grant-owned fact before considering the mutable +`consumed_at_millis` marker. `ResidentSelfTerminalAck` is no longer a launch +authority; it is Heartbeat-facing notification and provenance. Its absence or +qualified lifecycle retirement cannot resurrect a grant. The consumed marker +proves preparation consumed launch authority; clearing it cannot reopen a +terminal grant after completion, cancellation, restart, stale-envelope +resolution, or marker regression. Imagination candidate time is part of that causal contract. A candidate must have a valid RFC3339 timestamp at or after its request timestamp. A diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 5078ff51..2809e662 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -1328,12 +1328,35 @@ grant, so schedule/action issuance cardinality is accepted. After expiry, Self nevertheless launched again. The typed diagnostic proved the active lease named the exact already-completed pulse-48 grant, not another -Heartbeat grant. This run is rejected and was stopped with receipts. The deeper -ownership rule is that `ResidentSelfTerminalAck`, not the mutable -`consumed_at_millis` marker, permanently kills its exact grant. Pending selection -and Heartbeat's unconsumed-grant fence now exclude every terminally acknowledged -grant. A focused test deliberately regresses a completed grant's consumed marker -to absent and proves it remains unselectable while a different Heartbeat turn may -still grant later pending pressure. Twenty-four resident, eight swarm, and eleven -heartbeat-state tests pass. Commit, push, package, and replay this terminal fence; -do not treat c778 as bounded endurance evidence. +Heartbeat grant. This run is rejected and was stopped with receipts. The first +repair treated `ResidentSelfTerminalAck` as grant death instead of the mutable +`consumed_at_millis` marker. Exact replay disproved that ownership cut. + +Exact `61d06140` packaged as warning-free 24-binary release +`sha256-07d63fb815aa2298b95f240d856e912ca41ed4dc70ebe17ed559fc29766b4a71` +with witness +`sha256-06cd8373ca37c29e0123298484a67b6346b4b8ec0b8c93cd959237b3d8b7787a`. +The fresh 7,668-file copied body under +`.epiphany-run/active-cognition5-61d06140` completed one typed turn, persisted +`nextEligibleAtMillis=1786308887955`, restarted Self with exit zero, and slept +through the deadline. Heartbeat issued no second grant. After expiry Self again +prepared the original grant. + +Typed inspection found no success acknowledgement for that grant and no +resident lifecycle-retention head. Singleton `ResidentSelfState` still retained +the completed closure and cooldown; stopping the rejected run later wrote the +expected shutdown-cancellation acknowledgement. The acknowledgement-only fence +was therefore built on separately retained evidence, not on the grant whose +launchability it tried to decide. + +Each `ResidentSelfHeartbeatGrant` now owns its own terminality. Completion and +cancellation write its terminal timestamp and status in the same CAS that clears +the exact active lease; cancellation also requeues the pressure in that CAS. +Pending selection and Heartbeat issuance consult the grant-owned terminal fact. +`ResidentSelfTerminalAck` is Heartbeat-facing notification and provenance, not +launch authority. The focused regression deletes the acknowledgement and clears +the grant's consumed marker, then proves the terminal grant remains dead while +later pressure may receive a new grant from a different Heartbeat turn. +Twenty-four resident, eight swarm, and eleven heartbeat-state tests pass. +Package and replay the exact committed source from a fresh accepted-idle copy; +do not accept c778 or 61d as bounded endurance evidence. diff --git a/state/map.yaml b/state/map.yaml index 90ef52ea..77b58f88 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -35,8 +35,8 @@ invariants: - Evidence and git retain history; this map retains only state that changes future decisions. 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, and exact 16c4b19f coordinator receipt and Heartbeat artifact retention are proven. Gamecult-ops 059821f makes journald the sole Yggdrasil supervisor/projector stream-retention owner. The exact 16c4b19f genuine-idle control completed 900 refused pulses with constant state, zero artifacts, flat RSS, and clean direct-PID exits. Exact c77824ef proves package authentication, typed completion, and restart-persistent cooldown, but its live replay showed a terminally acknowledged grant could become selectable again after restart. Source now makes terminal acknowledgement the irreversible grant-death authority; another exact-package replay remains required. Broad session/model/event/tool retention and stable Starfire firewall ownership remain open. Yggdrasil is the small public crossing body, never the release forge. - latest_phase: Exact c77824ef packaged as warning-free 24-binary release sha256-e0b7c5cf54c4fb62929d91326c4604e8ad486c59411d6b2509de9182e7a83482 with witness sha256-f923a10c4a96b4301a952c3f874a913535f3165fee531034bbce077811a5629b. A fresh 7,668-file accepted-idle copy matched with zero hash differences. Its exact typed turn completed, persisted nextEligibleAtMillis=1786307607233, and a zero-exit Self restart slept through the deadline. Heartbeat issued no second grant, proving the schedule/action issuance fence. After expiry, however, preparation selected the exact already-completed grant again; diagnostic evidence bound the active lease to the same grant ID while Heartbeat remained on its original turn. Receipts are under .epiphany-run/active-cognition4-c77824ef and the run is rejected. Pending-grant selection and Heartbeat's unconsumed-grant exclusion now treat any ResidentSelfTerminalAck as irreversible closure for its exact grant, even if consumed_at_millis regresses. Twenty-four resident, eight swarm, and eleven heartbeat-state tests pass; packaging and exact replay of this terminal fence are open. + 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, and exact 16c4b19f coordinator receipt and Heartbeat artifact retention are proven. Gamecult-ops 059821f makes journald the sole Yggdrasil supervisor/projector stream-retention owner. The exact 16c4b19f genuine-idle control completed 900 refused pulses with constant state, zero artifacts, flat RSS, and clean direct-PID exits. Exact c77824ef and 61d06140 prove package authentication, typed completion, restart-persistent cooldown, and one-grant-per-Heartbeat-turn issuance; neither proves bounded active endurance because the completed grant became selectable again. The 61d run showed the terminal acknowledgement itself was absent while singleton Self closure state survived. Source now makes each ResidentSelfHeartbeatGrant own its own terminality; acknowledgements remain Heartbeat-facing evidence. Another exact-package replay remains required. Broad session/model/event/tool retention and stable Starfire firewall ownership remain open. Yggdrasil is the small public crossing body, never the release forge. + latest_phase: Exact 61d06140 packaged as warning-free 24-binary release sha256-07d63fb815aa2298b95f240d856e912ca41ed4dc70ebe17ed559fc29766b4a71 with witness sha256-06cd8373ca37c29e0123298484a67b6346b4b8ec0b8c93cd959237b3d8b7787a. A fresh 7,668-file accepted-idle copy matched with zero hash differences. Its exact typed turn completed, persisted nextEligibleAtMillis=1786308887955, and a zero-exit Self restart slept through the deadline. Heartbeat issued no second grant. After expiry, preparation nevertheless selected the exact completed grant. Typed inspection found no completion acknowledgement and no lifecycle-retention head for that run, while ResidentSelfState retained closure/cooldown and shutdown later wrote a cancellation acknowledgement. Receipts are under .epiphany-run/active-cognition5-61d06140 and the run is rejected. Completion and cancellation now mark the exact ResidentSelfHeartbeatGrant terminal in the same CAS that clears its active lease; pending selection and Heartbeat issuance read grant-owned terminality before the mutable consumed marker. The focused test deletes the acknowledgement and regresses consumed_at_millis, then proves the exact grant remains dead and a later Heartbeat turn may still grant later pressure. Twenty-four resident, eight swarm, and eleven heartbeat-state tests pass; packaging and exact replay of this grant-owned terminal fence are open. operational_state: local_worktree: coordinator_receipt_retention_packaged_proven operator_wireguard: restored @@ -68,8 +68,8 @@ current_status: starfire_linux_modeling_peak: 109887488_bytes_resident_body_plus_modeling_circuit yggdrasil_epiphany_service_contract: repaired_in_gamecult_ops_812b427_not_installed resident_physiology: authenticated_9b8df0b4_c005_bound_to_eyes_tools_nervous_system_with_217dd_and_bd96305e_helpers_running - unresolved_authority: Coordinator receipt, Heartbeat pulse-artifact, deployed supervisor/projector log retention, genuine-idle resource plateau, one exact live typed-fulfillment closure, restart-persistent cooldown refusal, and schedule/action issuance cardinality are accepted. The c778 endurance body is rejected because preparation relaunched its exact terminally acknowledged grant after restart. The terminal-acknowledgement grant-death fence is tested source only. Broader semantic/runtime histories remain unbounded pending a typed archived-session owner. Repository Body observation still performs two authenticated full-tree Git index/manifest passes. Execute-mode workers require a persistent process body. Keyed storage has not earned live migration. One Discord consequence remains blocked by the absent Yggdrasil credential. - next_action: Commit and push terminal-acknowledgement grant death, package and authenticate the exact source, then replay from a fresh accepted-idle copy. Require restart and cooldown expiry to leave the acknowledged grant permanently unselectable; later pressure may launch only from a new grant owned by a different Heartbeat schedule/action after the first acknowledgement closes. Prove bounded plateau/retention, clean direct-PID exits, and zero external consequence. Preserve active c005. Do not compact session/model/event/tool history until typed archived-session ownership exists. + unresolved_authority: Coordinator receipt, Heartbeat pulse-artifact, deployed supervisor/projector log retention, genuine-idle resource plateau, one exact live typed-fulfillment closure, restart-persistent cooldown refusal, and schedule/action issuance cardinality are accepted. The c778 and 61d endurance bodies are rejected because preparation relaunched their exact completed grant after restart. Grant-owned terminality is tested source only. Broader semantic/runtime histories remain unbounded pending a typed archived-session owner. Repository Body observation still performs two authenticated full-tree Git index/manifest passes. Execute-mode workers require a persistent process body. Keyed storage has not earned live migration. One Discord consequence remains blocked by the absent Yggdrasil credential. + next_action: Commit and push exact-grant-owned terminality, package and authenticate the exact source, then replay from a fresh accepted-idle copy. Require restart and cooldown expiry to leave the completed grant permanently unselectable even with its acknowledgement absent and consumed marker regressed; later pressure may launch only from a new grant owned by a different Heartbeat schedule/action. Prove bounded plateau/retention, clean direct-PID exits, and zero external consequence. Preserve active c005. Do not compact session/model/event/tool history until typed archived-session ownership exists. active_subgoals: - Prove Persona, Self, Eyes, Modeling, Imagination, Hands, Soul, Mind, Continuity, and nervous-system behavior individually.