Move coverage recovery into projector authority

This commit is contained in:
Meta Vens 2026-07-18 14:54:03 +01:00
commit 0601e28048
9 changed files with 1118 additions and 128 deletions

View file

@ -57,17 +57,18 @@ use epiphany_core::{EpiphanyPackagedReleaseEntry, authenticate_epiphany_packaged
use epiphany_core::{
ProcessInstanceIdentity, ProcessInstanceObservation,
WORKSPACE_COVERAGE_PROCESS_LAUNCH_SCHEMA_VERSION, WorkspaceCoverageManagedProcessLaunchEntry,
WorkspaceCoverageProcessBootstrap, authenticate_workspace_coverage_managed_process_launch,
WorkspaceCoverageProcessBootstrap, authenticate_current_workspace_coverage_claim_sight,
authenticate_workspace_coverage_managed_process_launch,
authenticate_workspace_coverage_provider_heartbeat,
authenticate_workspace_coverage_termination_with_envelope_digest, capture_process_instance,
current_workspace_coverage_recovery_target,
load_latest_workspace_coverage_managed_process_launch,
load_latest_workspace_coverage_provider_heartbeat,
load_workspace_coverage_process_termination_observation, native_boot_identity,
observe_process_instance, open_default_host_identity, recover_workspace_coverage_projection,
sign_workspace_coverage_launch, workspace_coverage_host_identity_record_digest,
observe_process_instance, open_default_host_identity, sign_workspace_coverage_launch,
workspace_coverage_host_identity_record_digest,
write_workspace_coverage_managed_process_launch, write_workspace_coverage_process_bootstrap,
write_workspace_coverage_process_termination_observation,
write_workspace_coverage_recovery_directive,
};
use epiphany_core::{
authenticate_current_workspace_coverage_advancement_sight,
@ -2226,11 +2227,18 @@ fn reconcile_workspace_coverage_projector(
);
return Ok(());
}
let runtime_store = args
.runtime_store
.clone()
.context("workspace coverage reconciliation requires --runtime-store")?;
let Some(target) = current_workspace_coverage_recovery_target(&runtime_store)? else {
let runtime_store = args.runtime_store.clone().context(
"workspace coverage reconciliation requires --runtime-store for Body/route sight",
)?;
let host = open_default_host_identity()
.context("workspace coverage reconciliation requires an enrolled host identity")?;
let Some(target) = authenticate_current_workspace_coverage_claim_sight(
&args.store,
&runtime_store,
&args.runtime_id,
host.entry(),
)?
else {
let latest = load_latest_workspace_coverage_managed_process_launch(
&args.store,
args.runtime_id.clone(),
@ -2315,19 +2323,17 @@ fn reconcile_workspace_coverage_projector(
}
};
let host = open_default_host_identity()
.context("workspace coverage reconciliation requires an enrolled host identity")?;
if load_workspace_coverage_process_termination_observation(
&args.store,
args.runtime_id.clone(),
&target.managed_process_launch_id,
&target.launch_id,
)?
.is_none()
{
if let Err(error) = write_workspace_coverage_process_termination_observation(
&args.store,
args.runtime_id.clone(),
&target.managed_process_launch_id,
&target.launch_id,
&host,
) {
println!(
@ -2349,11 +2355,11 @@ fn reconcile_workspace_coverage_projector(
authenticate_workspace_coverage_termination_with_envelope_digest(
&args.store,
args.runtime_id.clone(),
&target.managed_process_launch_id,
&target.launch_id,
host.entry(),
)?;
let replacement_evidence = CoverageReplacementEvidence {
old_launch_id: target.managed_process_launch_id.clone(),
old_launch_id: target.launch_id.clone(),
termination_id: termination.termination_id.clone(),
termination_envelope_digest: termination_digest,
};
@ -2362,7 +2368,7 @@ fn reconcile_workspace_coverage_projector(
args.runtime_id.clone(),
)?
.filter(|launch| {
launch.replaces_launch_id.as_deref() == Some(target.managed_process_launch_id.as_str())
launch.replaces_launch_id.as_deref() == Some(target.launch_id.as_str())
&& launch.replaces_termination_id.as_deref()
== Some(termination.termination_id.as_str())
});
@ -2405,28 +2411,24 @@ fn reconcile_workspace_coverage_projector(
let Some(ready) = ready else {
anyhow::bail!("workspace coverage replacement did not publish signed readiness in time");
};
let recovered = recover_workspace_coverage_projection(
&runtime_store,
let directive = write_workspace_coverage_recovery_directive(
&args.store,
&runtime_store,
&args.runtime_id,
host.entry(),
&target.managed_process_launch_id,
&target,
&replacement.launch_id,
&ready.heartbeat_id,
&target.claim_id,
&host,
)?;
println!(
"{}",
serde_json::to_string_pretty(&json!({
"schemaVersion": "epiphany.workspace_coverage_reconcile.v0",
"status": "recovered",
"status": "recovery-directed",
"serviceId": policy.service_id,
"oldClaimId": target.claim_id,
"newClaimId": recovered.claim_id,
"claimEpoch": recovered.claim_epoch,
"replacementLaunchId": replacement.launch_id,
"recoveryReceiptId": recovered.recovery_receipt_id,
"recoveryReceiptDigest": recovered.recovery_receipt_digest,
"directiveId": directive.directive_id,
"restarted": true,
"privateStateExposed": false,
}))?
@ -3935,10 +3937,14 @@ mod semantic_projector_authority_tests {
let readiness = body
.rfind("load_latest_workspace_coverage_provider_heartbeat")
.unwrap();
let recovery = body.rfind("recover_workspace_coverage_projection").unwrap();
let recovery = body
.rfind("write_workspace_coverage_recovery_directive")
.unwrap();
assert!(termination < launch && launch < readiness && readiness < recovery);
assert!(body.contains("write_workspace_coverage_process_termination_observation"));
assert!(body.contains("status == \"ready\""));
assert!(!body.contains("open_workspace_coverage_authority"));
assert!(!body.contains("recover_workspace_coverage_projection"));
}
#[test]

View file

@ -8,13 +8,16 @@ use crate::default_substrate_gate_cultnet_contracts;
use crate::packaged_release::{EpiphanyPackagedReleaseEntry, EpiphanyPackagedReleaseHead};
use crate::workspace_coverage_process_documents::{
WORKSPACE_COVERAGE_ADVANCEMENT_SIGHT_SCHEMA_VERSION,
WORKSPACE_COVERAGE_CLAIM_SIGHT_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROCESS_EVIDENCE_HEAD_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROCESS_LAUNCH_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROCESS_TERMINATION_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROVIDER_HEARTBEAT_SCHEMA_VERSION,
WORKSPACE_COVERAGE_RECOVERY_DIRECTIVE_SCHEMA_VERSION,
WORKSPACE_COVERAGE_TERMINAL_SIGHT_SCHEMA_VERSION, WorkspaceCoverageAdvancementSightEntry,
WorkspaceCoverageManagedProcessLaunchEntry, WorkspaceCoverageProcessEvidenceHead,
WorkspaceCoverageProcessTerminationObservationEntry, WorkspaceCoverageProviderHeartbeatEntry,
WorkspaceCoverageClaimSightEntry, WorkspaceCoverageManagedProcessLaunchEntry,
WorkspaceCoverageProcessEvidenceHead, WorkspaceCoverageProcessTerminationObservationEntry,
WorkspaceCoverageProviderHeartbeatEntry, WorkspaceCoverageRecoveryDirectiveEntry,
WorkspaceCoverageTerminalSightEntry,
};
use crate::workspace_coverage_projection_progress::{
@ -2665,6 +2668,8 @@ cultmesh_documents!(EpiphanyCultMeshDocuments {
WorkspaceCoverageProcessTerminationObservationEntry => WORKSPACE_COVERAGE_PROCESS_TERMINATION_SCHEMA_VERSION,
WorkspaceCoverageProjectionProgressEntry => WORKSPACE_COVERAGE_PROJECTION_PROGRESS_SCHEMA_VERSION,
WorkspaceCoverageAdvancementSightEntry => WORKSPACE_COVERAGE_ADVANCEMENT_SIGHT_SCHEMA_VERSION,
WorkspaceCoverageClaimSightEntry => WORKSPACE_COVERAGE_CLAIM_SIGHT_SCHEMA_VERSION,
WorkspaceCoverageRecoveryDirectiveEntry => WORKSPACE_COVERAGE_RECOVERY_DIRECTIVE_SCHEMA_VERSION,
WorkspaceCoverageTerminalSightEntry => WORKSPACE_COVERAGE_TERMINAL_SIGHT_SCHEMA_VERSION,
EpiphanyPackagedReleaseEntry => crate::packaged_release::EPIPHANY_PACKAGED_RELEASE_SCHEMA_VERSION,
EpiphanyPackagedReleaseHead => crate::packaged_release::EPIPHANY_PACKAGED_RELEASE_HEAD_SCHEMA_VERSION,

View file

@ -1197,15 +1197,20 @@ pub use workspace_coverage_process_bootstrap::{
};
pub use workspace_coverage_process_documents::{
WORKSPACE_COVERAGE_ADVANCEMENT_SIGHT_SCHEMA_VERSION, WORKSPACE_COVERAGE_ADVANCEMENT_SIGHT_TYPE,
WORKSPACE_COVERAGE_CLAIM_SIGHT_SCHEMA_VERSION, WORKSPACE_COVERAGE_CLAIM_SIGHT_TYPE,
WORKSPACE_COVERAGE_PROCESS_LAUNCH_LATEST_KEY, WORKSPACE_COVERAGE_PROCESS_LAUNCH_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROCESS_LAUNCH_TYPE, WORKSPACE_COVERAGE_PROCESS_TERMINATION_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROCESS_TERMINATION_TYPE, WORKSPACE_COVERAGE_PROVIDER_HEARTBEAT_LATEST_KEY,
WORKSPACE_COVERAGE_PROVIDER_HEARTBEAT_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROVIDER_HEARTBEAT_TYPE, WORKSPACE_COVERAGE_TERMINAL_SIGHT_SCHEMA_VERSION,
WORKSPACE_COVERAGE_PROVIDER_HEARTBEAT_TYPE,
WORKSPACE_COVERAGE_RECOVERY_DIRECTIVE_SCHEMA_VERSION,
WORKSPACE_COVERAGE_RECOVERY_DIRECTIVE_TYPE, WORKSPACE_COVERAGE_TERMINAL_SIGHT_SCHEMA_VERSION,
WORKSPACE_COVERAGE_TERMINAL_SIGHT_TYPE, WorkspaceCoverageAdvancementSightEntry,
WorkspaceCoverageManagedProcessLaunchEntry,
WorkspaceCoverageClaimSightEntry, WorkspaceCoverageManagedProcessLaunchEntry,
WorkspaceCoverageProcessTerminationObservationEntry, WorkspaceCoverageProviderHeartbeatEntry,
WorkspaceCoverageTerminalSightEntry, authenticate_current_workspace_coverage_advancement_sight,
WorkspaceCoverageRecoveryDirectiveEntry, WorkspaceCoverageTerminalSightEntry,
authenticate_current_workspace_coverage_advancement_sight,
authenticate_current_workspace_coverage_claim_sight,
authenticate_current_workspace_coverage_terminal_sight,
authenticate_workspace_coverage_managed_process_launch,
authenticate_workspace_coverage_process_termination_observation,
@ -1222,7 +1227,7 @@ pub use workspace_coverage_process_documents::{
workspace_coverage_host_identity_record_digest, workspace_coverage_launch_statement,
workspace_coverage_termination_statement, write_workspace_coverage_managed_process_launch,
write_workspace_coverage_process_termination_observation,
write_workspace_coverage_provider_heartbeat,
write_workspace_coverage_provider_heartbeat, write_workspace_coverage_recovery_directive,
};
pub use workspace_coverage_projection_progress::{
WORKSPACE_COVERAGE_PROJECTION_PROGRESS_SCHEMA_VERSION,
@ -1234,10 +1239,8 @@ pub use workspace_coverage_projection_progress::{
};
pub use workspace_coverage_projector::{
WORKSPACE_COVERAGE_MAXIMUM_FILE_BYTES, WorkspaceCoverageRecoveryOutcome,
WorkspaceCoverageRecoveryTarget, WorkspaceCoverageTerminalAuthority,
authenticate_current_workspace_coverage_terminal_authority,
authenticate_workspace_coverage_recovery_receipt, current_workspace_coverage_recovery_target,
recover_workspace_coverage_projection,
WorkspaceCoverageTerminalAuthority, authenticate_current_workspace_coverage_terminal_authority,
authenticate_workspace_coverage_recovery_receipt,
};
pub use workspace_coverage_projector_service::WorkspaceCoverageProjectorConfig;
pub use workspace_coverage_projector_service::WorkspaceCoverageProjectorPulseStatus;

File diff suppressed because it is too large Load diff

View file

@ -107,14 +107,6 @@ pub(crate) struct WorkspaceCoverageObservedBinding {
vector_binding_set_sha256: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct WorkspaceCoverageRecoveryTarget {
pub claim_id: String,
pub claim_epoch: u64,
pub plan_id: String,
pub managed_process_launch_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct WorkspaceCoverageRecoveryOutcome {
pub claim_id: String,
@ -2107,34 +2099,8 @@ pub(crate) fn acquire_workspace_coverage_projection(
/// Atomically transfers a projection lease only after CultMesh proves the old
/// process dead and the replacement process ready. This does not launch either
/// process; the supervisor must establish the evidence ordering first.
pub fn current_workspace_coverage_recovery_target(
runtime_store: impl AsRef<Path>,
) -> Result<Option<WorkspaceCoverageRecoveryTarget>> {
let runtime_store = runtime_store.as_ref();
let body_basis = observe_runtime_repository_body_basis(runtime_store)?;
let coverage = crate::open_workspace_coverage_authority(runtime_store)?;
let opening = coverage.store.pull_all()?;
let claim_key = workspace_coverage_claim_key(&body_basis.observation_id, body_basis.generation);
let Some(claim_env) = find(&opening, CLAIM_TYPE, &claim_key) else {
return Ok(None);
};
let claim: WorkspaceCoverageProjectionClaim = decode(claim_env)?;
let attempt_env = find(&opening, ATTEMPT_TYPE, &claim.attempt_id)
.ok_or_else(|| anyhow!("workspace coverage current attempt is absent"))?;
let attempt: WorkspaceCoverageProjectionAttempt = decode(attempt_env)?;
validate_claim_attempt_link(&claim, &attempt)?;
if claim.status != "running" {
return Ok(None);
}
Ok(Some(WorkspaceCoverageRecoveryTarget {
claim_id: claim.claim_id,
claim_epoch: claim.claim_epoch,
plan_id: claim.plan_id,
managed_process_launch_id: claim.managed_process_launch_id,
}))
}
pub fn recover_workspace_coverage_projection(
pub(crate) fn recover_workspace_coverage_projection_with_authority(
coverage: &crate::WorkspaceCoverageAuthority,
runtime_store: impl AsRef<Path>,
cultmesh_store: impl AsRef<Path>,
runtime_id: &str,
@ -2185,6 +2151,14 @@ pub fn recover_workspace_coverage_projection(
&replacement_launch.launch_id,
)?
.ok_or_else(|| anyhow!("workspace coverage recovery replacement has no current heartbeat"))?;
let (latest, _) = authenticate_workspace_coverage_provider_heartbeat_with_envelope_digest(
cultmesh_store,
runtime_id,
&latest.heartbeat_id,
host,
)?;
let ready_at = chrono::DateTime::parse_from_rfc3339(&ready.observed_at_utc)?;
let latest_at = chrono::DateTime::parse_from_rfc3339(&latest.observed_at_utc)?;
if old_launch.launch_id == replacement_launch.launch_id
|| replacement_launch.replaces_launch_id.as_deref() != Some(old_launch.launch_id.as_str())
|| replacement_launch.replaces_termination_id.as_deref()
@ -2194,9 +2168,14 @@ pub fn recover_workspace_coverage_projection(
.as_deref()
!= Some(termination_digest.as_str())
|| ready.launch_id != replacement_launch.launch_id
|| latest.heartbeat_id != ready.heartbeat_id
|| ready.status != "ready"
|| ready.sequence == 0
|| latest.launch_id != ready.launch_id
|| latest.provider_incarnation_id != ready.provider_incarnation_id
|| latest.provider_public_key != ready.provider_public_key
|| latest.status != "ready"
|| latest.sequence < ready.sequence
|| latest_at < ready_at
{
bail!("workspace coverage recovery replacement is not exact and ready");
}
@ -2212,7 +2191,6 @@ pub fn recover_workspace_coverage_projection(
RepositoryBodyReadSession::open(runtime_store, &body_basis)?;
let body_opening = SingleFileMessagePackBackingStore::new(&body_store).pull_all()?;
let body_authority = exact_body_authority(&body_opening, &body_basis)?;
let coverage = crate::open_workspace_coverage_authority(runtime_store)?;
let opening = coverage.store.pull_all()?;
let claim_key = workspace_coverage_claim_key(&body_basis.observation_id, body_basis.generation);
let claim_env = find(&opening, CLAIM_TYPE, &claim_key)
@ -2222,6 +2200,47 @@ pub fn recover_workspace_coverage_projection(
.ok_or_else(|| anyhow!("workspace coverage recovery running attempt is absent"))?;
let old_attempt: WorkspaceCoverageProjectionAttempt = decode(attempt_env)?;
validate_claim_attempt_link(&old_claim, &old_attempt)?;
// The coverage CAS may have committed before the successor projector could
// publish its claim sight. Replaying the exact host directive must observe
// that committed transfer, not attempt a second transfer or strand recovery.
if old_claim.claim_id != expected_old_claim_id
&& let (Some(recovery_id), Some(expected_digest)) = (
old_claim.recovery_receipt_id.as_deref(),
old_claim.recovery_receipt_digest.as_deref(),
)
{
let receipt_env = find(&opening, RECOVERY_TYPE, recovery_id)
.ok_or_else(|| anyhow!("recovered successor receipt is absent"))?;
let receipt: WorkspaceCoverageRecoveryReceipt = decode(receipt_env)?;
validate_recovery_receipt(&receipt)?;
let receipt_digest = cultcache_envelope_digest(receipt_env);
if receipt_digest != expected_digest
|| receipt.old_claim_id != expected_old_claim_id
|| receipt.termination_id != termination.termination_id
|| receipt.termination_envelope_digest != termination_digest.as_str()
|| receipt.replacement_launch_id != replacement_launch.launch_id
|| receipt.replacement_launch_envelope_digest != replacement_launch_digest.as_str()
|| receipt.ready_heartbeat_id != ready.heartbeat_id
|| receipt.ready_heartbeat_envelope_digest != ready_digest.as_str()
|| receipt.new_claim_id != old_claim.claim_id
|| receipt.new_attempt_id != old_attempt.attempt_id
|| receipt.new_claim_epoch != old_claim.claim_epoch
|| old_claim.managed_process_launch_id != replacement_launch.launch_id
|| old_claim.executor_incarnation != replacement_launch.provider_incarnation_id
|| old_claim.status != "running"
|| old_attempt.status != "running"
{
bail!("workspace coverage recovered successor disagrees with exact directive evidence");
}
return Ok(WorkspaceCoverageRecoveryOutcome {
claim_id: old_claim.claim_id,
claim_epoch: old_claim.claim_epoch,
managed_process_launch_id: old_claim.managed_process_launch_id,
executor_incarnation: old_claim.executor_incarnation,
recovery_receipt_id: recovery_id.to_string(),
recovery_receipt_digest: receipt_digest,
});
}
if old_claim.schema_version != CLAIM_SCHEMA
|| old_attempt.schema_version != ATTEMPT_SCHEMA
|| old_claim.status != "running"
@ -5157,7 +5176,6 @@ mod tests {
.is_none()
);
drop(authority);
assert!(current_workspace_coverage_recovery_target(&runtime)?.is_none());
Ok(())
}

View file

@ -1,6 +1,10 @@
use crate::repository_body_observer::RepositoryBodyReadSession;
use crate::semantic_backend::{OllamaConfig, OllamaEmbedder, QdrantBackend, QdrantConfig};
use crate::workspace_coverage_process_documents::publish_workspace_coverage_terminal_sight;
use crate::workspace_coverage_process_documents::{
authenticate_current_workspace_coverage_claim_sight,
authenticate_workspace_coverage_recovery_directive, publish_workspace_coverage_claim_sight,
publish_workspace_coverage_terminal_sight,
};
use crate::workspace_coverage_projector::{
WorkspaceCoverageAcquireResult, WorkspaceCoverageCurrentState,
WorkspaceCoverageProjectionExecutionAuthority, acquire_workspace_coverage_projection,
@ -214,6 +218,53 @@ impl WorkspaceCoverageProjectorServiceBody {
}
fn pulse_inner(&mut self) -> Result<WorkspaceCoverageProjectorServicePulse> {
let authority = self.execution_authority.as_ref().ok_or_else(|| {
anyhow!("workspace coverage projector has no installed execution authority")
})?;
let has_successor_sight = authenticate_current_workspace_coverage_claim_sight(
&authority.local_verse_store,
&self.runtime_store,
&authority.runtime_id,
&authority.trusted_host,
)?
.is_some_and(|sight| {
sight.launch_id == self.managed_process_launch_id && sight.recovery_receipt_id.is_some()
});
if !has_successor_sight
&& let Some(directive) = authenticate_workspace_coverage_recovery_directive(
&authority.local_verse_store,
&self.runtime_store,
&authority.runtime_id,
&self.managed_process_launch_id,
&authority.trusted_host,
)?
{
let basis = load_current_runtime_repository_body_basis(&self.runtime_store)?;
if directive.workspace_id != basis.workspace_id
|| directive.body_binding_sha256 != basis.body_binding_sha256
|| directive.body_observation_id != basis.observation_id
|| directive.body_generation != basis.generation
|| directive.manifest_root_sha256 != basis.manifest_root_sha256
|| directive.coverage_store_binding_id
!= self.coverage_authority.store_binding.binding_id
|| directive.coverage_store_binding_envelope_digest
!= self.coverage_authority.store_binding_envelope_sha256
|| directive.coverage_store_file_identity
!= self.coverage_authority.store_binding.store_file_identity
|| directive.runtime_coverage_route_envelope_digest
!= self
.coverage_authority
.runtime_coverage_route_envelope_sha256
{
bail!("workspace coverage recovery directive disagrees with held authority");
}
crate::workspace_coverage_projector::recover_workspace_coverage_projection_with_authority(
&self.coverage_authority, &self.runtime_store, &authority.local_verse_store,
&authority.runtime_id, &authority.trusted_host, &directive.old_launch_id,
&directive.replacement_launch_id, &directive.replacement_ready_heartbeat_id,
&directive.old_claim_id,
)?;
}
// Retirement is derived from typed Body history and is deliberately
// performed before the idle fast path. Qdrant never nominates its own
// garbage and incompatible same-name collections stop the pulse.
@ -308,6 +359,20 @@ impl WorkspaceCoverageProjectorServiceBody {
let authority = self.execution_authority.as_ref().ok_or_else(|| {
anyhow!("workspace coverage projector has no installed execution authority")
})?;
// Publish the exact provider-signed lease before the first backend
// operation. Recovery sight must exist even when the projector dies
// before it can mint a progress checkpoint.
publish_workspace_coverage_claim_sight(
&authority.local_verse_store,
&self.runtime_store,
&self.coverage_authority,
&acquisition,
&authority.runtime_id,
&self.managed_process_launch_id,
&authority.trusted_host,
&authority.provider_signing_key,
chrono::Utc::now(),
)?;
let receipt = execute_workspace_coverage_projection(
&acquisition,
&prepared,
@ -441,4 +506,18 @@ mod tests {
)?;
Ok(())
}
#[test]
fn acquired_claim_is_visible_before_any_projection_backend_work() {
let source = include_str!("workspace_coverage_projector_service.rs");
let acquired = source
.find("WorkspaceCoverageAcquireResult::Acquired(acquisition)")
.unwrap();
let body = &source[acquired..source.find("#[cfg(test)]").unwrap()];
let sight = body
.find("publish_workspace_coverage_claim_sight(")
.unwrap();
let execution = body.find("execute_workspace_coverage_projection(").unwrap();
assert!(sight < execution, "claim sight must precede backend work");
}
}

View file

@ -2413,3 +2413,80 @@ supervisor binaries pass. The old all-at-once executor survives only under
deployed body. The next authority cut is Idunn and aggregate health: consume the
exact provider progress document with a no-advance lease, never a generic job
progress noun or total projection wall clock.
## Organizational Epiphany is the product, not a remote-control experiment (2026-07-18)
The Yggdrasil deployment is the first ordinary organizational Epiphany body.
It must remain awake without continual instruction: Modeling persistently maps
the bounded domain into typed Mind state, Self extrapolates pressure and
direction from that map, and Imagination authors inspectable improvement and
feature proposals. This initiative is advisory until the appropriate adoption
and consequence authorities act; operator inactivity permits observation,
modeling, and proposals, not merge, publication, deployment, or scope growth.
The repository Persona is the organization's shared social crossing. Members
may talk to it, correct it, and provide feedback through ordinary Discord
conversation. Persona owns discussion and legibility. Conversation produces
typed feedback pressure for Modeling, Imagination, and Mind review; it does not
directly mutate canonical Mind, invoke Hands, authorize a release, or command
Idunn. Authenticated operational capabilities such as brake, objective intake,
adoption approval, release authorization, and deployment remain distinct typed
Bifrost routes with explicit receipts. VoidBot observes the room and Bifrost
routes the typed crossing; do not invent a second Discord bot or grant ordinary
chat ambient actuator authority.
The July 22 continuity criterion is stronger than remote command. Yggdrasil
must host the resident scheduler/coordinator, model runtime, tool spine, Persona
crossing, writable domain worktree, persistent Mind/Modeling state, and local
credentials. Starfire may be absent through August 5. The offline rehearsal
must prove conversation/feedback -> persistent domain map -> Imagination
proposal -> explicit adoption/review -> Hands consequence -> Bifrost exact
release authority -> Idunn deployment receipt, plus the negative that
conversation alone cannot cross any later boundary.
The immediate live wound precedes that work. The workspace projector is the
lifetime owner of `workspace-coverage.cc`, but the supervisor currently opens
that private store to discover and perform recovery. Replace that transitive
authority leak with a provider-signed claim sight published immediately after
acquisition and a host-signed recovery directive consumed by the replacement
projector. Heartbeat remains liveness only. The supervisor must never open or
mutate the coverage store; it declares recovery only after authenticating the
replacement claim sight. Keep Epiphany and Idunn stopped on Yggdrasil until the
corrected exact release is authorized through Bifrost and deployed through
Idunn. No host reboot is authorized.
## Workspace-coverage recovery ownership cut complete locally (2026-07-18)
The supervisor no longer opens or mutates `workspace-coverage.cc`, directly or
through an imported recovery helper. The lifetime projector owner publishes a
provider-signed claim sight before its first backend operation. Claim sight is
keyed to the exact current Body observation and generation and binds the exact
launch, provider key, coverage-store binding/file/route, Body basis, claim,
attempt envelope, plan, and recovery lineage. A signed sight from an older Body
is not current recovery authority.
After exact termination and replacement readiness, the supervisor publishes
one immutable host-signed recovery directive. It binds the authenticated old
claim sight, termination, replacement launch, readiness heartbeat, Body, and
coverage route by exact envelope digests. Reconciliation reauthenticates and
returns the same signed directive byte-for-byte; a later heartbeat cannot
rewrite it, and conflicting lineage is refused. Provider heartbeats now retain
immutable per-heartbeat evidence beside the latest pointer because durable
termination and recovery documents may cite an earlier heartbeat. Causally safe
bounded retirement remains future work; naive deletion is forbidden.
The replacement projector authenticates the directive and performs the
recovery CAS through its already-held `WorkspaceCoverageAuthority`. Recovery is
idempotent across the CAS-to-successor-sight crash window: an exact committed
successor and receipt are returned on replay, then ordinary acquisition
republishes successor claim sight. A directive naming readiness heartbeat H
remains valid when the same launch/provider has advanced normally to ready
H+1. Heartbeat remains liveness evidence and does not own the lease.
Focused proof passes: eight process-document tests, the exclusive lifetime
owner test, supervisor authority-order/prohibition test, pre-checkpoint sight,
stale-Body refusal, H/H+1 consumption, immutable directive reissue, conflicting
lineage refusal, exact CAS replay, successor sight publication, `cargo check
--bins`, and `git diff --check`. Soul found no remaining P0/P1/P2. This code is
ready to commit and push, then cross Bifrost/Idunn as an exact release while the
host remains braked.

Binary file not shown.

View file

@ -739,4 +739,4 @@ current_status:
- Release `sha256-c94109f94ee42c1257089830f399cb87cd5ad672772c274194371995ce4df923` is the first deployed immutable sibling generation. Native packaging builds from detached exact source commit `dd80f4a51c18425a6665710698a357be61154abf`, initializes pinned submodules, uses the tracked lockfile under `--locked`, and publishes four exact binaries plus a typed CultCache witness/head only after atomic directory publication and byte verification. Task Scheduler pins release id/digest and the witnessed supervisor path; Idunn reauthenticates the complete set and reserved policy role paths. Current-boot proof: reconciler PID 21228 launched direct child 22736; witnessed Mind/Modeling queries ranked semantically; killing that exact-path child caused Idunn to launch PID 19748 with receipt `86a42d51-9930-4b5d-9e61-e74c82a0d808`, ready heartbeat `4fc91977-b635-474b-812b-c364847e2b4b`, and witnessed executable digest `sha256-1060dd64e8c2b520ec8744b67e8306db04a6618d463fc2117c352adf9e30e6b0`. This closes current-boot artifact generation and recurrence, not reboot/logon survival.
- Release `sha256-6f9ab4848207a110e7e3836f41e6a74c0f463369ad4b04ce2d0d3831a6b262ae` packages repository-readiness source commit `360dcb433dda9599fca14282592608d26b8b6cc8`; witnessed Idunn PID 29476 directly owns witnessed projector PID 22840 with launch receipt `50879209-b65f-4411-ae3f-6f647d37bf42` and ready heartbeat `134df620-9e20-4220-ad4e-117ea4ca8188`. Deployment exposed receipt-v2 migration pressure: v1 receipts became correctly ineligible, but the old Succeeded pulse shortcut kept both partitions idle. The shortcut is now cut in source. Valid v2 terminal evidence derives Ready; an exact same-obligation succeeded claim opens Repair only after its consumed grant/recovery authority and exact succeeded attempt are authenticated. Failed repair retries through execute at the next epoch. Forged predecessor authority cannot be laundered by a repair grant.
- Yggdrasil exact-SHA pressure release `586147a751c6eec2d59cd8dc10bd17ce0d02a4d1` proved useful GPU work but failed deployment honestly. GTX 1080 stayed near saturation at 2,419 MiB; bounded four-text requests completed continuously. Mind published 215 vectors, while workspace coverage completed 3,389 Ollama HTTP calls total (about 13.3k workspace chunks after Mind) before Idunn's 50-minute candidate-health deadline at 2026-07-17T01:23:50+02:00. Idunn then stopped the service, published no deployment witness, and reported no exact-candidate daemon-health proof; the Modeling collection remained at the inherited 22 points because the monolithic executor had not yet published its accumulated vectors. This is failure evidence for the execution/deployment contract, not for GPU acceleration. Total wall-time extension is forbidden as the repair.
next_action: Migrate workspace projection obligation/plan/claim/attempt/recovery/checkpoint/progress/receipt/head ownership into the pinned transactional workspace-coverage store, bind/bootstrap it on every deployment path, and cut all Body/Verse projection writers and fallback reads. Preserve Body as observations only. Do not redeploy c94fa580 or any descendant as a live candidate until that cut is complete and verified against body.cc rewrite, store-substitution, stale-Body claim, atomic checkpoint/progress, restart, and terminal-proof negatives. No reboot is authorized.
next_action: "Commit and push the verified workspace-coverage recovery ownership cut, authorize its exact SHA through Bifrost, deploy only through Idunn, and prove Ygg-local exclusive ownership, recovery replay, bounded Body/coverage I/O, Qdrant progress, GPU work, terminal health, and service restart while the host remains braked until admission. Then package the resident organizational swarm (scheduler/coordinator, model runtime, tool spine, Persona), provision its writable domain worktree and local credentials, wire VoidBot/Bifrost Discord feedback and separately authenticated operations, and complete a Starfire-offline rehearsal before 2026-07-22. Ordinary Persona conversation may create typed feedback pressure but cannot adopt Mind state, invoke Hands, authorize release, or deploy. No host reboot is authorized."