Publish repo work proof rows to CultMesh

This commit is contained in:
Meta Vens 2026-06-20 03:43:26 +01:00
commit 462869ed75
8 changed files with 488 additions and 5 deletions

View file

@ -21,6 +21,7 @@ use epiphany_core::EpiphanyCultMeshEveSurfaceStateEntry;
use epiphany_core::EpiphanyCultMeshImaginationConsensusReceiptEntry;
use epiphany_core::EpiphanyCultMeshOdinAdvertisementEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkOverviewEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkPublicProofEntry;
use epiphany_core::EpiphanyCultMeshSwarmBrakeEntry;
use epiphany_core::EpiphanyCultMeshWorkLoopTelemetryEntry;
use epiphany_core::EpiphanyLocalVerseContext;
@ -48,6 +49,7 @@ use epiphany_core::load_epiphany_cultmesh_daemon_service_lifecycle_receipts;
use epiphany_core::load_epiphany_cultmesh_daemon_tool_directory;
use epiphany_core::load_epiphany_cultmesh_eve_surface_directory;
use epiphany_core::load_epiphany_cultmesh_repo_work_overviews;
use epiphany_core::load_epiphany_cultmesh_repo_work_public_proofs;
use epiphany_core::load_epiphany_cultmesh_swarm_brake;
use epiphany_core::load_latest_epiphany_cultmesh_agent_state_soa_summary;
use epiphany_core::load_latest_epiphany_cultmesh_bifrost_body_change_publication_intent;
@ -61,6 +63,7 @@ use epiphany_core::load_latest_epiphany_cultmesh_eve_connection_intent;
use epiphany_core::load_latest_epiphany_cultmesh_eve_connection_receipt;
use epiphany_core::load_latest_epiphany_cultmesh_imagination_consensus_receipt;
use epiphany_core::load_latest_epiphany_cultmesh_repo_work_overview;
use epiphany_core::load_latest_epiphany_cultmesh_repo_work_public_proof;
use epiphany_core::open_epiphany_cultmesh_node;
use epiphany_core::query_epiphany_local_verse_context;
use epiphany_core::seed_epiphany_local_verse_context;
@ -3442,6 +3445,7 @@ fn run_cli() -> Result<()> {
&[],
&[missing_artifact_action],
&[],
&[],
);
if !missing_artifact_rows.iter().any(|row| {
row.priority == 50
@ -3491,6 +3495,7 @@ fn run_cli() -> Result<()> {
&[],
&[synthetic_runbook_action],
&[],
&[],
);
if !synthetic_artifact_rows.iter().any(|row| {
row.priority == 50
@ -3945,10 +3950,13 @@ struct SwarmOverviewReport {
service_execution_failed_check_tui_rows: Vec<String>,
repo_work_overview_rows: Vec<RepoWorkOverviewRow>,
repo_work_overview_tui_rows: Vec<String>,
repo_work_public_proof_rows: Vec<RepoWorkPublicProofRow>,
repo_work_public_proof_tui_rows: Vec<String>,
latest_repo_work_overview_id: Option<String>,
latest_repo_work_gate: Option<String>,
latest_repo_work_blocker: Option<String>,
latest_repo_work_next_safe_move: Option<String>,
latest_repo_work_public_proof: Option<String>,
topology_report: ClusterTopologyReport,
daemon_report: DaemonLivenessReport,
surface_report: EveSurfaceReport,
@ -3976,6 +3984,27 @@ struct RepoWorkOverviewRow {
private_state_exposed: bool,
}
#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct RepoWorkPublicProofRow {
public_proof_id: String,
workspace: String,
item: String,
branch: String,
current_gate: String,
blocker: String,
next_safe_move: String,
changed_path_count: usize,
commit_sha: String,
soul_verdict: String,
upstream_main_synced: bool,
artifact_row_count: u32,
publication_row_count: u32,
public_proof_ref: String,
public_proof_sha256: String,
private_state_exposed: bool,
}
#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct SwarmActionRow {
@ -4060,10 +4089,14 @@ struct SwarmOverviewOutput {
repo_work_overview_count: usize,
repo_work_overview_rows: Vec<RepoWorkOverviewRow>,
repo_work_overview_tui_rows: Vec<String>,
repo_work_public_proof_count: usize,
repo_work_public_proof_rows: Vec<RepoWorkPublicProofRow>,
repo_work_public_proof_tui_rows: Vec<String>,
latest_repo_work_overview: Option<String>,
latest_repo_work_gate: Option<String>,
latest_repo_work_blocker: Option<String>,
latest_repo_work_next_safe_move: Option<String>,
latest_repo_work_public_proof: Option<String>,
policy_covered_count: usize,
policy_enabled_count: usize,
policy_disabled_count: usize,
@ -4127,10 +4160,14 @@ impl SwarmOverviewOutput {
repo_work_overview_count: report.repo_work_overview_rows.len(),
repo_work_overview_rows: report.repo_work_overview_rows,
repo_work_overview_tui_rows: report.repo_work_overview_tui_rows,
repo_work_public_proof_count: report.repo_work_public_proof_rows.len(),
repo_work_public_proof_rows: report.repo_work_public_proof_rows,
repo_work_public_proof_tui_rows: report.repo_work_public_proof_tui_rows,
latest_repo_work_overview: report.latest_repo_work_overview_id,
latest_repo_work_gate: report.latest_repo_work_gate,
latest_repo_work_blocker: report.latest_repo_work_blocker,
latest_repo_work_next_safe_move: report.latest_repo_work_next_safe_move,
latest_repo_work_public_proof: report.latest_repo_work_public_proof,
policy_covered_count: report.policy_report.covered_count,
policy_enabled_count: report.policy_report.enabled_count,
policy_disabled_count: report.policy_report.disabled_count,
@ -4186,10 +4223,14 @@ struct SwarmTriageOutput {
repo_work_overview_count: usize,
repo_work_overview_rows: Vec<RepoWorkOverviewRow>,
repo_work_overview_tui_rows: Vec<String>,
repo_work_public_proof_count: usize,
repo_work_public_proof_rows: Vec<RepoWorkPublicProofRow>,
repo_work_public_proof_tui_rows: Vec<String>,
latest_repo_work_overview: Option<String>,
latest_repo_work_gate: Option<String>,
latest_repo_work_blocker: Option<String>,
latest_repo_work_next_safe_move: Option<String>,
latest_repo_work_public_proof: Option<String>,
poked_daemon_count: usize,
pokes: Vec<serde_json::Value>,
commands: serde_json::Value,
@ -4248,10 +4289,14 @@ impl SwarmTriageOutput {
repo_work_overview_count: report.repo_work_overview_rows.len(),
repo_work_overview_rows: report.repo_work_overview_rows,
repo_work_overview_tui_rows: report.repo_work_overview_tui_rows,
repo_work_public_proof_count: report.repo_work_public_proof_rows.len(),
repo_work_public_proof_rows: report.repo_work_public_proof_rows,
repo_work_public_proof_tui_rows: report.repo_work_public_proof_tui_rows,
latest_repo_work_overview: report.latest_repo_work_overview_id,
latest_repo_work_gate: report.latest_repo_work_gate,
latest_repo_work_blocker: report.latest_repo_work_blocker,
latest_repo_work_next_safe_move: report.latest_repo_work_next_safe_move,
latest_repo_work_public_proof: report.latest_repo_work_public_proof,
poked_daemon_count,
pokes,
commands: json!({
@ -4451,6 +4496,7 @@ fn swarm_action_rows(
service_execution_failed_check_rows: &[EpiphanyServiceExecutionAuditCheck],
service_execution_runbook_actions: &[ServiceExecutionRunbookAction],
repo_work_overviews: &[EpiphanyCultMeshRepoWorkOverviewEntry],
repo_work_public_proofs: &[EpiphanyCultMeshRepoWorkPublicProofEntry],
) -> (Vec<SwarmActionRow>, Vec<String>) {
let mut rows = Vec::new();
let mut service_execution_check_counts = BTreeMap::<String, (usize, usize)>::new();
@ -4698,6 +4744,12 @@ fn swarm_action_rows(
private_state_exposed: runbook_action.private_state_exposed,
});
}
for (index, public_proof) in repo_work_public_proofs.iter().take(5).enumerate() {
rows.push(repo_work_public_proof_action_row(
public_proof,
60 + index as u32,
));
}
if rows.is_empty() {
rows.push(SwarmActionRow {
priority: 100,
@ -4801,6 +4853,59 @@ fn repo_work_peer_tui_rows(rows: &[RepoWorkOverviewRow]) -> Vec<String> {
.collect()
}
fn repo_work_public_proof_rows(
public_proofs: &[EpiphanyCultMeshRepoWorkPublicProofEntry],
) -> (Vec<RepoWorkPublicProofRow>, Vec<String>) {
let rows = public_proofs
.iter()
.map(repo_work_public_proof_row)
.collect::<Vec<_>>();
let tui_rows = rows
.iter()
.map(repo_work_public_proof_tui_row)
.collect::<Vec<_>>();
(rows, tui_rows)
}
fn repo_work_public_proof_row(
proof: &EpiphanyCultMeshRepoWorkPublicProofEntry,
) -> RepoWorkPublicProofRow {
RepoWorkPublicProofRow {
public_proof_id: proof.public_proof_id.clone(),
workspace: proof.workspace.clone(),
item: proof.item.clone(),
branch: proof.branch.clone(),
current_gate: proof.current_gate.clone(),
blocker: proof.blocker.clone(),
next_safe_move: proof.next_safe_move.clone(),
changed_path_count: proof.changed_paths.len(),
commit_sha: proof.commit_sha.clone(),
soul_verdict: proof.soul_verdict.clone(),
upstream_main_synced: proof.upstream_main_synced,
artifact_row_count: proof.artifact_row_count,
publication_row_count: proof.publication_row_count,
public_proof_ref: proof.public_proof_ref.clone(),
public_proof_sha256: proof.public_proof_sha256.clone(),
private_state_exposed: proof.private_state_exposed,
}
}
fn repo_work_public_proof_tui_row(row: &RepoWorkPublicProofRow) -> String {
format!(
"REPO-WORK-PUBLIC-PROOF | item={} | gate={} | branch={} | commit={} | artifacts={} | publicationRows={} | upstreamMainSynced={} | proof={} | sha256={} | private={}",
row.item,
row.current_gate,
row.branch,
row.commit_sha,
row.artifact_row_count,
row.publication_row_count,
row.upstream_main_synced,
row.public_proof_ref,
row.public_proof_sha256,
row.private_state_exposed
)
}
fn repo_work_overview_action_row(
overview: &EpiphanyCultMeshRepoWorkOverviewEntry,
priority: u32,
@ -4849,6 +4954,55 @@ fn repo_work_overview_action_row(
}
}
fn repo_work_public_proof_action_row(
proof: &EpiphanyCultMeshRepoWorkPublicProofEntry,
priority: u32,
) -> SwarmActionRow {
SwarmActionRow {
priority,
family: "repo-work-public-proof".to_string(),
status: proof.current_gate.clone(),
lifecycle_owner: "Gjallar".to_string(),
hosted_body: "repo-work".to_string(),
action: format!(
"Read redacted public proof {} for item {}; Bifrost owns any public publication or credit consequence.",
proof.public_proof_id, proof.item
),
wrapper_mode: "repo-work-public-proof".to_string(),
wrapper_command: format!(
"epiphany-work export-proof --workspace \"{}\" --item \"{}\" --local-verse-store <store>",
proof.workspace, proof.item
),
operator_artifact_ref: proof.public_proof_ref.clone(),
operator_artifact_status: if proof.public_proof_ref == "none" {
"none".to_string()
} else {
"external-ref".to_string()
},
operator_artifact_sha256: proof.public_proof_sha256.clone(),
operator_artifact_execution_command: "none".to_string(),
operator_aftercare_command: "none".to_string(),
completion_audit_wrapper_mode: "bifrost-ledger".to_string(),
completion_audit_wrapper_command: WRAPPER_BIFROST_LEDGER_COMMAND.to_string(),
authority_gate: "repo.work.public_proof_readback".to_string(),
effect_class: "repo-work-public-proof-readback".to_string(),
mutates_state: false,
requires_elevated_authority: false,
service_execution_failed_check_count: 0,
service_execution_missing_check_count: 0,
service_id: "none".to_string(),
service_route: "none".to_string(),
reason: format!(
"Redacted proof has artifacts={} publicationRows={} upstreamMainSynced={} sha256={}",
proof.artifact_row_count,
proof.publication_row_count,
proof.upstream_main_synced,
proof.public_proof_sha256
),
private_state_exposed: proof.private_state_exposed,
}
}
fn swarm_action_tui_row(row: &SwarmActionRow) -> String {
format!(
"{:03} | {} | {} | {} | {} | owner={} | hostedBody={} | service={} | route={} | command={} | mutates={} | elevated={} | failedChecks={} | missingChecks={} | artifact={} | sha256={} | exec={} | audit={} | aftercare={}",
@ -5230,12 +5384,40 @@ fn load_repo_work_overview_queue(
Ok((latest_repo_work_overview, repo_work_overviews))
}
fn load_repo_work_public_proofs(
args: &Args,
) -> Result<(
Option<EpiphanyCultMeshRepoWorkPublicProofEntry>,
Vec<EpiphanyCultMeshRepoWorkPublicProofEntry>,
)> {
let latest_public_proof =
load_latest_epiphany_cultmesh_repo_work_public_proof(&args.store, args.runtime_id.clone())?;
let mut public_proofs =
load_epiphany_cultmesh_repo_work_public_proofs(&args.store, args.runtime_id.clone())?;
if let Some(latest) = latest_public_proof.as_ref() {
if !public_proofs
.iter()
.any(|proof| proof.public_proof_id == latest.public_proof_id)
{
public_proofs.push(latest.clone());
public_proofs.sort_by(|a, b| {
b.generated_at
.cmp(&a.generated_at)
.then_with(|| a.public_proof_id.cmp(&b.public_proof_id))
});
}
}
Ok((latest_public_proof, public_proofs))
}
fn load_swarm_overview_report(args: &Args) -> Result<SwarmOverviewReport> {
let topology = load_epiphany_cultmesh_cluster_topology(&args.store, args.runtime_id.clone())?;
let topology_report = cluster_topology_report(&topology);
let liveness = load_epiphany_cultmesh_daemon_liveness(&args.store, args.runtime_id.clone())?;
let daemon_report = daemon_liveness_report(&liveness);
let (latest_repo_work_overview, repo_work_overviews) = load_repo_work_overview_queue(args)?;
let (latest_repo_work_public_proof, repo_work_public_proofs) =
load_repo_work_public_proofs(args)?;
let directory =
load_epiphany_cultmesh_eve_surface_directory(&args.store, args.runtime_id.clone())?;
let surface_report = eve_surface_report(&directory, &repo_work_overviews);
@ -5448,6 +5630,8 @@ fn load_swarm_overview_report(args: &Args) -> Result<SwarmOverviewReport> {
.collect::<Vec<_>>();
let (repo_work_overview_rows, repo_work_overview_tui_rows) =
repo_work_overview_rows(&repo_work_overviews);
let (repo_work_public_proof_rows, repo_work_public_proof_tui_rows) =
repo_work_public_proof_rows(&repo_work_public_proofs);
let (swarm_action_rows, swarm_action_tui_rows) = swarm_action_rows(
&liveness_status,
&tool_host_attention_rows,
@ -5456,6 +5640,7 @@ fn load_swarm_overview_report(args: &Args) -> Result<SwarmOverviewReport> {
&service_execution_failed_check_rows,
&service_execution_runbook_actions,
&repo_work_overviews,
&repo_work_public_proofs,
);
let private_state_exposed = daemon_report
.rows
@ -5466,6 +5651,9 @@ fn load_swarm_overview_report(args: &Args) -> Result<SwarmOverviewReport> {
|| repo_work_overviews
.iter()
.any(|overview| overview.private_state_exposed)
|| repo_work_public_proofs
.iter()
.any(|proof| proof.private_state_exposed)
|| service_execution_private_state_exposed
|| service_lifecycle_rows
.iter()
@ -5482,6 +5670,9 @@ fn load_swarm_overview_report(args: &Args) -> Result<SwarmOverviewReport> {
let latest_repo_work_next_safe_move = latest_repo_work_overview
.as_ref()
.map(|overview| overview.next_safe_move.clone());
let latest_repo_work_public_proof = latest_repo_work_public_proof
.as_ref()
.map(|proof| proof.public_proof_id.clone());
Ok(SwarmOverviewReport {
status,
liveness_status,
@ -5506,10 +5697,13 @@ fn load_swarm_overview_report(args: &Args) -> Result<SwarmOverviewReport> {
service_execution_failed_check_tui_rows,
repo_work_overview_rows,
repo_work_overview_tui_rows,
repo_work_public_proof_rows,
repo_work_public_proof_tui_rows,
latest_repo_work_overview_id,
latest_repo_work_gate,
latest_repo_work_blocker,
latest_repo_work_next_safe_move,
latest_repo_work_public_proof,
topology_report,
daemon_report,
surface_report,

View file

@ -5,7 +5,9 @@ use chrono::DateTime;
use chrono::Utc;
use epiphany_core::EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID;
use epiphany_core::EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_SCHEMA_VERSION;
use epiphany_core::EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION;
use epiphany_core::EpiphanyCultMeshRepoWorkOverviewEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkPublicProofEntry;
use epiphany_core::HANDS_ACTION_INTENT_SCHEMA_VERSION;
use epiphany_core::HANDS_COMMAND_RECEIPT_TYPE;
use epiphany_core::HANDS_COMMIT_RECEIPT_TYPE;
@ -45,6 +47,7 @@ use epiphany_core::runtime_hands_action_review;
use epiphany_core::runtime_hands_commit_receipt;
use epiphany_core::runtime_latest_hands_receipt_chain_after;
use epiphany_core::write_epiphany_cultmesh_repo_work_overview;
use epiphany_core::write_epiphany_cultmesh_repo_work_public_proof;
use serde_json::Value;
use serde_json::json;
use sha2::Digest;
@ -272,6 +275,8 @@ struct ExportProofArgs {
accept_receipt: Option<PathBuf>,
artifact_dir: Option<PathBuf>,
output: Option<PathBuf>,
local_verse_store: Option<PathBuf>,
runtime_id: String,
}
#[derive(Clone, Debug)]
@ -978,6 +983,8 @@ fn parse_export_proof_args(args: impl Iterator<Item = String>) -> Result<ExportP
let mut accept_receipt = None;
let mut artifact_dir = None;
let mut output = None;
let mut local_verse_store = None;
let mut runtime_id = "repo-swarm-local".to_string();
let mut args = args.peekable();
while let Some(arg) = args.next() {
@ -987,6 +994,10 @@ fn parse_export_proof_args(args: impl Iterator<Item = String>) -> Result<ExportP
"--accept-receipt" => accept_receipt = Some(take_path(&mut args, "--accept-receipt")?),
"--artifact-dir" => artifact_dir = Some(take_path(&mut args, "--artifact-dir")?),
"--output" | "--export-path" => output = Some(take_path(&mut args, "--output")?),
"--local-verse-store" | "--store" => {
local_verse_store = Some(take_path(&mut args, "--local-verse-store")?);
}
"--runtime-id" => runtime_id = take_string(&mut args, "--runtime-id")?,
other => return Err(anyhow!("unexpected export-proof argument {other:?}")),
}
}
@ -996,6 +1007,8 @@ fn parse_export_proof_args(args: impl Iterator<Item = String>) -> Result<ExportP
accept_receipt,
artifact_dir,
output,
local_verse_store,
runtime_id,
})
}
@ -3557,14 +3570,92 @@ fn run_export_proof(args: ExportProofArgs) -> Result<Value> {
});
let public_bundle = repo_work_public_proof_bundle(&overview)?;
write_json(&output, &public_bundle)?;
let public_proof_sha256 = file_sha256(&output)?;
let local_verse_store = args
.local_verse_store
.unwrap_or_else(|| workspace.join(".epiphany").join("local-verse.ccmp"));
let artifact_row_count = public_bundle
.get("artifactRows")
.and_then(Value::as_array)
.map(|rows| rows.len())
.unwrap_or(0);
let publication_row_count = public_bundle
.get("publicationRows")
.and_then(Value::as_array)
.map(|rows| rows.len())
.unwrap_or(0);
let public_proof_tui_rows = repo_work_public_proof_tui_rows(
&public_bundle,
&output,
&public_proof_sha256,
artifact_row_count,
publication_row_count,
);
let entry = EpiphanyCultMeshRepoWorkPublicProofEntry {
schema_version: EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION.to_string(),
runtime_id: args.runtime_id.clone(),
verse_id: EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID.to_string(),
public_proof_id: format!("repo-work-public-proof-{item_slug}"),
generated_at: string_from_json(&public_bundle, &["generatedAt"])
.unwrap_or_else(|| Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true)),
workspace: workspace.display().to_string(),
item: item.clone(),
branch: string_from_json(&public_bundle, &["branch"]).unwrap_or_else(|| "unknown".to_string()),
current_gate: string_from_json(&public_bundle, &["currentGate"])
.unwrap_or_else(|| "unknown".to_string()),
blocker: string_from_json(&public_bundle, &["blocker"]).unwrap_or_else(|| "none".to_string()),
next_safe_move: string_from_json(&public_bundle, &["nextSafeMove"])
.unwrap_or_else(|| "none".to_string()),
changed_paths: public_bundle
.get("changedPaths")
.and_then(Value::as_array)
.map(|paths| {
paths
.iter()
.filter_map(Value::as_str)
.map(ToString::to_string)
.collect::<Vec<_>>()
})
.unwrap_or_default(),
commit_sha: string_from_json(&public_bundle, &["commitSha"]).unwrap_or_else(|| "none".to_string()),
soul_verdict: string_from_json(&public_bundle, &["soulVerdict"]).unwrap_or_else(|| "none".to_string()),
upstream_main_synced: public_bundle
.get("upstreamMainSynced")
.and_then(Value::as_bool)
.unwrap_or(false),
artifact_row_count: artifact_row_count as u32,
publication_row_count: publication_row_count as u32,
public_proof_ref: output.display().to_string(),
public_proof_sha256: public_proof_sha256.clone(),
tui_rows: public_proof_tui_rows,
private_state_exposed: false,
notes: vec![
"Repo work public proof is a redacted local Verse index for public/Bifrost transport; raw receipt bodies, local receipt paths, worker thought, and private Verse contents remain sealed.".to_string(),
"Gjallar/Odin may discover this proof, but Bifrost still owns publication, labor ledger, credit, and public consequence.".to_string(),
],
};
let written_public_proof =
write_epiphany_cultmesh_repo_work_public_proof(&local_verse_store, entry)?;
let verse_projection = json!({
"localVerseStore": local_verse_store,
"documentType": "epiphany.cultmesh.repo_work_public_proof",
"publicProofId": written_public_proof.public_proof_id,
"latestKey": "gamecult-local/repo-work-public-proof/latest",
"publicProofRef": written_public_proof.public_proof_ref,
"publicProofSha256": written_public_proof.public_proof_sha256,
"tuiRows": written_public_proof.tui_rows,
"privateStateExposed": written_public_proof.private_state_exposed
});
Ok(json!({
"schemaVersion": "epiphany.repo_work_public_proof_export.v0",
"status": "public-proof-exported",
"workspace": workspace,
"item": item,
"outputPath": output,
"outputSha256": public_proof_sha256,
"sourceOverviewReceiptPath": overview["receiptPath"],
"publicProofBundle": public_bundle,
"verseProjection": verse_projection,
"privateStateExposed": false,
"nextSafeMove": "Share the public proof bundle with maintainers or Bifrost; keep raw worker thoughts and local receipt bodies sealed."
}))
@ -4748,6 +4839,30 @@ fn repo_work_public_artifact_row(row: &Value) -> Value {
})
}
fn repo_work_public_proof_tui_rows(
bundle: &Value,
output: &Path,
sha256: &str,
artifact_row_count: usize,
publication_row_count: usize,
) -> Vec<String> {
vec![format!(
"PUBLIC-PROOF | item={} | gate={} | branch={} | commit={} | artifacts={} | publicationRows={} | upstreamMainSynced={} | proof={} | sha256={} | private=false",
string_from_json(bundle, &["item"]).unwrap_or_else(|| "unknown".to_string()),
string_from_json(bundle, &["currentGate"]).unwrap_or_else(|| "unknown".to_string()),
string_from_json(bundle, &["branch"]).unwrap_or_else(|| "unknown".to_string()),
string_from_json(bundle, &["commitSha"]).unwrap_or_else(|| "none".to_string()),
artifact_row_count,
publication_row_count,
bundle
.get("upstreamMainSynced")
.and_then(Value::as_bool)
.unwrap_or(false),
output.display(),
sha256
)]
}
fn sync_receipt_upstream_main_synced(receipt: &Value) -> Option<bool> {
receipt
.get("upstreamMainSynced")
@ -5358,7 +5473,7 @@ fn print_usage() {
publish --workspace <repo> [--item <id>] --change-summary <text> --justification <text> --verification-receipt <ref> --review-receipt <ref> --ledger-entry-id <id> --pull-request-url <url> --pull-request-title <text>\n\
sync --workspace <repo> [--item <id>] [--publish-receipt <path>] [--upstream-ref origin/main] --merge-receipt <ref>\n\
overview --workspace <repo> [--item <id>] [--accept-receipt <path>] [--no-write]\n\
export-proof --workspace <repo> [--item <id>] [--accept-receipt <path>] [--output <path>]\n\
export-proof --workspace <repo> [--item <id>] [--accept-receipt <path>] [--output <path>] [--local-verse-store <path>] [--runtime-id repo-swarm-local]\n\
tick --workspace <repo> [--item <id>] [--local-verse-store <path>] [--runtime-store <path>] [--dry-run]\n\
queue-run --workspace <repo> [--local-verse-store <path>] [--runtime-id repo-swarm-local] [--max-items 1] [--dry-run]"
);

View file

@ -76,6 +76,12 @@ pub const EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_SCHEMA_VERSION: &str =
"epiphany.cultmesh.repo_work_overview.v0";
pub const EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_LATEST_KEY: &str =
"gamecult-local/repo-work-overview/latest";
pub const EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_TYPE: &str =
"epiphany.cultmesh.repo_work_public_proof";
pub const EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION: &str =
"epiphany.cultmesh.repo_work_public_proof.v0";
pub const EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_LATEST_KEY: &str =
"gamecult-local/repo-work-public-proof/latest";
pub const EPIPHANY_CULTMESH_VERSE_POLICY_TYPE: &str = "epiphany.cultmesh.verse_policy";
pub const EPIPHANY_CULTMESH_VERSE_POLICY_SCHEMA_VERSION: &str = "epiphany.cultmesh.verse_policy.v0";
pub const EPIPHANY_CULTMESH_GLOBAL_ROOM_POLICY_TYPE: &str = "epiphany.cultmesh.global_room_policy";
@ -740,6 +746,58 @@ pub struct EpiphanyCultMeshRepoWorkOverviewEntry {
pub notes: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.cultmesh.repo_work_public_proof",
schema = "EpiphanyCultMeshRepoWorkPublicProofEntry"
)]
pub struct EpiphanyCultMeshRepoWorkPublicProofEntry {
#[cultcache(key = 0)]
pub schema_version: String,
#[cultcache(key = 1)]
pub runtime_id: String,
#[cultcache(key = 2)]
pub verse_id: String,
#[cultcache(key = 3)]
pub public_proof_id: String,
#[cultcache(key = 4)]
pub generated_at: String,
#[cultcache(key = 5)]
pub workspace: String,
#[cultcache(key = 6)]
pub item: String,
#[cultcache(key = 7)]
pub branch: String,
#[cultcache(key = 8)]
pub current_gate: String,
#[cultcache(key = 9)]
pub blocker: String,
#[cultcache(key = 10)]
pub next_safe_move: String,
#[cultcache(key = 11)]
pub changed_paths: Vec<String>,
#[cultcache(key = 12)]
pub commit_sha: String,
#[cultcache(key = 13)]
pub soul_verdict: String,
#[cultcache(key = 14)]
pub upstream_main_synced: bool,
#[cultcache(key = 15)]
pub artifact_row_count: u32,
#[cultcache(key = 16)]
pub publication_row_count: u32,
#[cultcache(key = 17)]
pub public_proof_ref: String,
#[cultcache(key = 18)]
pub public_proof_sha256: String,
#[cultcache(key = 19)]
pub tui_rows: Vec<String>,
#[cultcache(key = 20)]
pub private_state_exposed: bool,
#[cultcache(key = 21)]
pub notes: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.cultmesh.verse_policy",
@ -2034,6 +2092,7 @@ cultmesh_documents!(EpiphanyCultMeshDocuments {
EpiphanyCultMeshWorkLoopTelemetryEntry => EPIPHANY_CULTMESH_WORK_LOOP_TELEMETRY_SCHEMA_VERSION,
EpiphanyCultMeshAgentStateSoaSummaryEntry => EPIPHANY_CULTMESH_AGENT_STATE_SOA_SUMMARY_SCHEMA_VERSION,
EpiphanyCultMeshRepoWorkOverviewEntry => EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_SCHEMA_VERSION,
EpiphanyCultMeshRepoWorkPublicProofEntry => EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION,
EpiphanyCultMeshVersePolicyEntry => EPIPHANY_CULTMESH_VERSE_POLICY_SCHEMA_VERSION,
EpiphanyCultMeshGlobalRoomPolicyEntry => EPIPHANY_CULTMESH_GLOBAL_ROOM_POLICY_SCHEMA_VERSION,
EpiphanyCultMeshClusterTopologyEntry => EPIPHANY_CULTMESH_CLUSTER_TOPOLOGY_SCHEMA_VERSION,
@ -4181,6 +4240,48 @@ pub fn load_epiphany_cultmesh_repo_work_overviews(
Ok(overviews)
}
pub fn write_epiphany_cultmesh_repo_work_public_proof(
store_path: impl AsRef<Path>,
proof: EpiphanyCultMeshRepoWorkPublicProofEntry,
) -> Result<EpiphanyCultMeshRepoWorkPublicProofEntry> {
validate_repo_work_public_proof(&proof)?;
let mut node = open_epiphany_cultmesh_node(&store_path, proof.runtime_id.clone())?;
let written = node.put(proof.public_proof_id.clone(), &proof)?;
node.put(
EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_LATEST_KEY,
&written,
)?;
node.flush()?;
Ok(written)
}
pub fn load_latest_epiphany_cultmesh_repo_work_public_proof(
store_path: impl AsRef<Path>,
runtime_id: impl Into<String>,
) -> Result<Option<EpiphanyCultMeshRepoWorkPublicProofEntry>> {
let node = open_epiphany_cultmesh_node(store_path, runtime_id)?;
node.get(EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_LATEST_KEY)
}
pub fn load_epiphany_cultmesh_repo_work_public_proofs(
store_path: impl AsRef<Path>,
runtime_id: impl Into<String>,
) -> Result<Vec<EpiphanyCultMeshRepoWorkPublicProofEntry>> {
let node = open_epiphany_cultmesh_node(store_path, runtime_id)?;
let mut proofs = node
.get_all_with_keys::<EpiphanyCultMeshRepoWorkPublicProofEntry>()?
.into_iter()
.filter(|(key, _)| key != EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_LATEST_KEY)
.map(|(_, proof)| proof)
.collect::<Vec<_>>();
proofs.sort_by(|a, b| {
b.generated_at
.cmp(&a.generated_at)
.then_with(|| a.public_proof_id.cmp(&b.public_proof_id))
});
Ok(proofs)
}
fn validate_repo_work_overview(overview: &EpiphanyCultMeshRepoWorkOverviewEntry) -> Result<()> {
if overview.private_state_exposed {
return Err(anyhow!("repo work overview must not expose private state"));
@ -4215,6 +4316,48 @@ fn validate_repo_work_overview(overview: &EpiphanyCultMeshRepoWorkOverviewEntry)
Ok(())
}
fn validate_repo_work_public_proof(proof: &EpiphanyCultMeshRepoWorkPublicProofEntry) -> Result<()> {
if proof.private_state_exposed {
return Err(anyhow!(
"repo work public proof must not expose private state"
));
}
if proof.schema_version != EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION {
return Err(anyhow!(
"repo work public proof schema_version must be {:?}",
EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION
));
}
if proof.verse_id != EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID {
return Err(anyhow!(
"repo work public proof belongs in local-area Verse {:?}",
EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID
));
}
if proof.public_proof_id.trim().is_empty() || proof.item.trim().is_empty() {
return Err(anyhow!(
"repo work public proof requires public_proof_id and item"
));
}
if proof.public_proof_ref.trim().is_empty() || proof.public_proof_sha256.trim().is_empty() {
return Err(anyhow!(
"repo work public proof requires artifact ref and sha256"
));
}
if proof.tui_rows.is_empty() {
return Err(anyhow!("repo work public proof requires compact TUI rows"));
}
if proof.tui_rows.iter().any(|row| {
let lower = row.to_ascii_lowercase();
lower.contains("rawresult") || lower.contains("receipt body") || lower.contains("thought")
}) {
return Err(anyhow!(
"repo work public proof rows must not expose raw worker payload names"
));
}
Ok(())
}
pub fn seed_epiphany_local_verse_context(
store_path: impl AsRef<Path>,
runtime_id: impl Into<String>,

View file

@ -206,6 +206,9 @@ pub use cultmesh_integration::EPIPHANY_CULTMESH_PERSONA_SPEECH_AUDIT_TYPE;
pub use cultmesh_integration::EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_LATEST_KEY;
pub use cultmesh_integration::EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_SCHEMA_VERSION;
pub use cultmesh_integration::EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_TYPE;
pub use cultmesh_integration::EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_LATEST_KEY;
pub use cultmesh_integration::EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION;
pub use cultmesh_integration::EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_TYPE;
pub use cultmesh_integration::EPIPHANY_CULTMESH_ROLE_REVIEW_EVENT_LATEST_KEY;
pub use cultmesh_integration::EPIPHANY_CULTMESH_ROLE_REVIEW_EVENT_SCHEMA_VERSION;
pub use cultmesh_integration::EPIPHANY_CULTMESH_ROLE_REVIEW_EVENT_TYPE;
@ -259,6 +262,7 @@ pub use cultmesh_integration::EpiphanyCultMeshOperatorSnapshotEntry;
pub use cultmesh_integration::EpiphanyCultMeshOperatorStatusEntry;
pub use cultmesh_integration::EpiphanyCultMeshPersonaSpeechAuditEntry;
pub use cultmesh_integration::EpiphanyCultMeshRepoWorkOverviewEntry;
pub use cultmesh_integration::EpiphanyCultMeshRepoWorkPublicProofEntry;
pub use cultmesh_integration::EpiphanyCultMeshRoleReviewEventEntry;
pub use cultmesh_integration::EpiphanyCultMeshSoulContractEntry;
pub use cultmesh_integration::EpiphanyCultMeshStatusEntry;
@ -315,6 +319,7 @@ pub use cultmesh_integration::load_epiphany_cultmesh_eve_surface_directory;
pub use cultmesh_integration::load_epiphany_cultmesh_operator_snapshot;
pub use cultmesh_integration::load_epiphany_cultmesh_operator_status;
pub use cultmesh_integration::load_epiphany_cultmesh_repo_work_overviews;
pub use cultmesh_integration::load_epiphany_cultmesh_repo_work_public_proofs;
pub use cultmesh_integration::load_epiphany_cultmesh_status;
pub use cultmesh_integration::load_epiphany_cultmesh_swarm_brake;
pub use cultmesh_integration::load_latest_epiphany_cultmesh_agent_state_soa_summary;
@ -338,6 +343,7 @@ pub use cultmesh_integration::load_latest_epiphany_cultmesh_operator_run_receipt
pub use cultmesh_integration::load_latest_epiphany_cultmesh_operator_snapshot;
pub use cultmesh_integration::load_latest_epiphany_cultmesh_persona_speech_audit;
pub use cultmesh_integration::load_latest_epiphany_cultmesh_repo_work_overview;
pub use cultmesh_integration::load_latest_epiphany_cultmesh_repo_work_public_proof;
pub use cultmesh_integration::load_latest_epiphany_cultmesh_role_review_event;
pub use cultmesh_integration::load_latest_epiphany_cultmesh_work_loop_telemetry;
pub use cultmesh_integration::open_epiphany_cultmesh_node;
@ -376,6 +382,7 @@ pub use cultmesh_integration::write_epiphany_cultmesh_operator_snapshot;
pub use cultmesh_integration::write_epiphany_cultmesh_operator_status;
pub use cultmesh_integration::write_epiphany_cultmesh_persona_speech_audit;
pub use cultmesh_integration::write_epiphany_cultmesh_repo_work_overview;
pub use cultmesh_integration::write_epiphany_cultmesh_repo_work_public_proof;
pub use cultmesh_integration::write_epiphany_cultmesh_role_review_event;
pub use cultmesh_integration::write_epiphany_cultmesh_soul_contracts;
pub use cultmesh_integration::write_epiphany_cultmesh_status;

View file

@ -714,6 +714,26 @@ default public proof path, carried eight artifact rows and three publication
rows, exposed zero artifact path fields, kept `rawReceiptBodies=false`, and
reported `private=false`.
The first public-proof Verse transport smoke made that export discoverable
through local CultMesh/Gjallar sight without handing publication authority to
the exporter. `epiphany-work export-proof --local-verse-store <repo>\.epiphany\local-verse.ccmp`
now writes `epiphany.cultmesh.repo_work_public_proof.v0` under
`gamecult-local/repo-work-public-proof/latest`, carrying item, gate, branch,
commit, artifact/publication row counts, upstream-main sync truth, public proof
artifact ref, SHA-256, compact `PUBLIC-PROOF` TUI rows, and
`privateStateExposed=false`. `epiphany-verse-query swarm-overview` reads that
history and emits `repoWorkPublicProofRows`, `repoWorkPublicProofTuiRows`,
`latestRepoWorkPublicProof`, plus non-mutating priority 60+
`repo-work-public-proof` action rows with `authorityGate=repo.work.public_proof_readback`,
`effectClass=repo-work-public-proof-readback`, `mutatesState=false`, and
`requiresElevatedAuthority=false`. Smoke artifacts
`.epiphany-smoke\checklist-note-20260620-031347\14-export-proof-verse.json`
and `15-swarm-overview-public-proof.json` proved latest
`repo-work-public-proof-checklist-request`, SHA-256
`e781e09c2ba340c8818d3ef95e54085ccd0c92c6a3b5f73cc4878fb224e49dff`, one
public proof row, one public proof action row, no mutation/elevation, and
`private=false`.
The first Verse projection smoke proved the local CultMesh sight path: overview
mirrored `repo-work-overview-verse-overview-request` into the repo-local Verse,
`epiphany-verse-query smoke --store <local-verse> --runtime-id repo-swarm-local`
@ -1179,8 +1199,11 @@ Required organs before MVP:
`epiphany-work export-proof` now writes a redacted
`epiphany.repo_work_public_proof_bundle.v0` artifact under
`.epiphany/public/proof-bundles/` with local paths and raw receipt bodies
removed. Remaining work is Bifrost/public Verse transport and UX polish, not
basic local public-proof export or Bifrost/GitHub/sync row visibility.
removed, and mirrors an `epiphany.cultmesh.repo_work_public_proof.v0` row
into local Verse for Gjallar/Odin sight. Remaining work is Bifrost public
publication/credit transport beyond local Verse plus UX polish, not basic
local public-proof export, local CultMesh readback, or Bifrost/GitHub/sync
row visibility.
Scheduler authority is intentionally narrow. It may advance
`accept -> plan -> run -> adopt -> execute` only when each upstream receipt

View file

@ -113,6 +113,7 @@ remembers doctrine; the branch remembers the blade.
- 2026-06-20: Local proof-bundle packaging is live. `epiphany-work overview` now embeds `epiphany.repo_work_proof_bundle.v0` with generated time, gate/blocker/next-safe-move, compact TUI rows, expected artifact paths, present/missing artifact status, document schema/status, SHA-256 receipt hashes, and `privateStateExposed=false`. Disposable proof `.epiphany-smoke\tick-close-20260620-025526\08-overview-proof-bundle.json` reported six present artifacts from accept through close with hashes, missing publish/sync rows, `awaiting-publication` / `bifrost-publication-missing`, and no private-state exposure. The next cut is richer model-authored safe families or published/credited proof-bundle depth, not another local proof-bundle wrapper.
- 2026-06-20: Published/credited proof-bundle rows are live. `epiphany-work overview` now adds `publicationRows` to `epiphany.repo_work_proof_bundle.v0`, lifting Bifrost intent/publication/GitHub/ledger/credit/PR fields, Hands commit/PR fields, and upstream-main ancestry fields from publish/sync receipts without granting publication, merge, scheduler, service lifecycle, cross-repo, or private-state authority. Disposable proof `.epiphany-smoke\checklist-note-20260620-031347\12-overview-published-proof.json` ran close -> publish -> sync -> overview after the checklist safe-family proof; overview reported `complete-or-awaiting-new-work`, `upstreamMainSynced=true` from `authority.upstreamMainSynced`, three publication rows, and `privateStateExposed=false`. The next cut is richer public/export packaging outside the local bundle or model-authored closure, not basic Bifrost/GitHub/sync row visibility.
- 2026-06-20: Public proof export is live. `epiphany-work export-proof` calls overview, distills the local `epiphany.repo_work_proof_bundle.v0` into redacted `epiphany.repo_work_public_proof_bundle.v0`, and writes `.epiphany/public/proof-bundles/repo-work-public-proof-<item>.json` by default without raw receipt bodies, local receipt paths, expected paths, worker thought, publication authority, or private Verse exposure. Disposable proof `.epiphany-smoke\checklist-note-20260620-031347\13-export-proof.json` reported eight artifact rows, three publication rows, zero artifact path fields, `rawReceiptBodies=false`, and `private=false`. The next cut is Bifrost/public Verse transport for exported proof, richer model-authored safe-family breadth, or richer model-authored closure; not another local public-proof export wrapper.
- 2026-06-20: Public proof local Verse transport is live. `epiphany-work export-proof --local-verse-store <repo>\.epiphany\local-verse.ccmp` now mirrors each redacted export as `epiphany.cultmesh.repo_work_public_proof.v0` under `gamecult-local/repo-work-public-proof/latest`, with compact `PUBLIC-PROOF` TUI rows, artifact/publication row counts, public proof artifact ref, SHA-256, upstream-main sync truth, and `privateStateExposed=false`. `epiphany-verse-query swarm-overview` reads those rows as `repoWorkPublicProofRows` / `repoWorkPublicProofTuiRows`, exposes `latestRepoWorkPublicProof`, and adds non-mutating/non-elevated `repo-work-public-proof` action rows owned by Gjallar sight while Bifrost still owns publication/credit consequence. Disposable proofs `.epiphany-smoke\checklist-note-20260620-031347\14-export-proof-verse.json` and `15-swarm-overview-public-proof.json` reported latest `repo-work-public-proof-checklist-request`, one public proof row, one action row, SHA-256 `e781e09c2ba340c8818d3ef95e54085ccd0c92c6a3b5f73cc4878fb224e49dff`, `mutates=false`, `elevated=false`, and `private=false`. The next cut is Bifrost/public publication transport beyond local Verse, richer safe-family breadth, or richer model-authored closure.
- 2026-06-20: Gjallar/swarm-overview now exposes repo-work overview history as first-class compact sight, Persona's public Eve surface lowers the same queue for peer-readable collaboration, and Self has a first runnable queue surface over it. `SwarmOverviewOutput` and `SwarmTriageOutput` include `repoWorkOverviewCount`, `repoWorkOverviewRows`, `repoWorkOverviewTuiRows`, `latestRepoWorkOverview`, `latestRepoWorkGate`, `latestRepoWorkBlocker`, and `latestRepoWorkNextSafeMove`; the shared `swarmActionRows` queue gets priority 35 `repo-work-overview` rows owned by Gjallar, hosted body `repo-work`, authority gate `repo.work.overview`, effect class `repo-work-readback`, no mutation, no elevation, proof-bundle ref, and private-state seal. `eve-surfaces`, direct `connect-eve`, and the globally invokable Persona `eve-connect` daemon tool readback expose public `REPO-WORK-PEER` rows with item, gate, blocker, next safe move, branch, publication, sync, and `private=false`. `epiphany-work queue-run` reads the same typed queue, selects current-repo rows at `ready-to-run`, `ready-to-adopt`, `ready-to-execute`, or `awaiting-closure`, delegates to `tick`, refreshes overview after real advancement, and wrapper `repo-work-queue-run` exposes the operator surface. Disposable proofs `.epiphany-smoke\gjallar-repo-work-queue-20260620-012027`, `.epiphany-smoke\eve-repo-work-queue-20260620-013322`, `.epiphany-smoke\queue-run-20260620-014314`, and wrapper artifact `local-20260620-014627-174-aada0241` prove two-item queue sight, Eve lowering, direct queue-run advancement, and wrapper dry-run without publication, merge, service lifecycle mutation, elevation, cross-repo mutation, or private-state exposure. The next cut is richer Persona-to-Imagination plan derivation, not another queue display surface.
- `service-execution-runbook` makes that next cut repeatable: it generates the exact elevated wrapper command sequence without mutating the service manager, continues after per-step failure to preserve more receipts, runs `service-execution-audit` in `finally`, exits nonzero if any step failed, and seals a typed runbook lifecycle receipt. Run the generated artifact only with explicit operator authority.
- `service-execution-audit` is the non-mutating acceptance proof after the elevated rite: it reports `complete` only when typed lifecycle receipts prove the runbook witness plus expected elevated chain, and otherwise reports the missing/failed sealed checks.

Binary file not shown.

View file

@ -88,7 +88,7 @@ active_subgoals:
- Keep the landed Phase 6 coordinator, limited safe-boundary CRRC automation, and pre-compaction checkpoint intervention ready for the next bridge-equipped dogfood run.
- Preserve the Ghostlight-derived heartbeat initiative seam: every lane, including coordinator/Self and Persona, has a organ-state record and competes for heartbeat slots through readiness/reaction timing; initiative heat can raise or cool global, group, arena, role, and agent tempo through typed heartbeat policy; active thinking freezes initiative until completion, so heat never queues a lane already mid-turn; idle winners ruminate instead of inventing project work, and sleep windows distill the accumulated thought pressure into reviewed self-memory or doctrine.
- Use `notes/epiphany-swarm-readiness-plan.md` as the live-fire direction gate. The local run path is a compass, not launch clearance: before unattended swarm operation, Epiphany needs typed pause/brake enforcement, one initiative scheduler, completion-gated cooldown, stale active-turn recovery receipts, parent-side Persona speech eligibility, memory lifecycle operations, and CultNet-first operator snapshots/intents/receipts. The local Verse brake document exists, `epiphany-verse-query swarm-brake` can engage/release it, `tools/epiphany_local_run.ps1` refuses live `plan`/`run`/`mvp` modes when the brake is engaged while leaving `status` readable, `epiphany-mvp-coordinator` checks the local Verse brake before app-server startup, and `epiphany-heartbeat-store` guards tick/pump/heat/queue-mention/routine when given `--local-verse-store`. Daemon liveness is now a typed local Verse authority: `epiphany-verse-query daemon-status` writes one daemon status without repainting the table, local Verse seeding preserves existing daemon statuses and swarm brakes, `invoke-tool` refuses when the host daemon is not ready or lacks `submitTypedToolIntent`, and both daemon tool invocation and lifecycle poke fail closed under an engaged matching brake. `epiphany-daemon-supervisor policy` writes durable per-daemon restart policy with command/args/cwd/cooldown/backoff/attempt state plus reconcile cadence and stale-heartbeat threshold; `epiphany-daemon-supervisor reconcile` loads that policy when no override command is supplied, refuses under a matching lifecycle brake, refuses during cooldown/backoff, writes daemon poke intent/receipt, updates daemon status, and updates policy attempt state; `epiphany-daemon-supervisor tick` is an explicit scheduler pulse that scans durable policies, records ready/noop pulses, skips before the configured reconcile interval, marks stale heartbeat status degraded, routes restarts through the same brake/cooldown/poke receipt path, and writes a latest `epiphany.cultmesh.daemon_scheduler_receipt.v0`; `epiphany-daemon-supervisor serve` runs that same pulse on a configurable cadence with bounded `--max-iterations` proof mode or unbounded service mode. `epiphany-daemon-supervisor service-plan`/`install-service` now writes a planned `epiphany.cultmesh.daemon_service_lifecycle_receipt.v0` for the `serve` command, while `service-launch`/`start-service` spawns that `serve` loop through the current executable or `--service-command`, can `--wait-child` for bounded proof, and records command/args/cwd, scheduler id, daemon selector, pid/exit/status, artifact ref, and private-state guard. `service-runbook`, `windows-service-install`/`service-install-plan`, `windows-service-status`, `windows-service-reconcile`, `windows-service-execution-readiness`, and `windows-service-start`/`stop` now record service lifecycle receipts through the same local Verse; the read-only status path has been proved against the real Windows `EventLog` service with receipt `daemon-service-lifecycle-receipt-windows-eventlog-proof-windows-service-status`, status `running`, exit code `0`, and `privateStateExposed=false`; the read-only service-policy reconciliation path has been proved for missing service, real-service drift against `EventLog`, lifecycle-brake refusal, and wrapper/local-Verse receipt `daemon-service-lifecycle-receipt-windows-eventlog-reconcile-proof-windows-service-reconcile`; execution readiness has been proved as a non-mutating `not-elevated` receipt through direct and wrapper paths; start/stop now produce non-mutating `start-planned`/`stop-planned` receipts unless `--execute-control`/`--execute-service-control` is passed, and wrapper `service-start-plan`/`service-stop-plan` proves those receipts against `EventLog`; explicit install/control execution now refuses as `execution-refused-not-elevated` with `executed=false` when the shell lacks Windows administrator authority, and wrapper `service-install-execute`, `service-start-execute`, and `service-stop-execute` prove those refusal receipts without mutation. Service lifecycle actions check the local Verse swarm brake before process launch, artifact writes, service-manager queries, service-policy reconciliation, execution-readiness checks, control planning, elevation-gated execution, or start/stop execution. The local wrapper builds/checks this binary.
- Use `notes/epiphany-repo-swarm-mvp-contract.md` as the authority correction and migration plan for repo-swarm autonomy. Autonomous branch-local work inside an Epiphany-owned repo Body is in scope and desired; the safety boundary is typed authority, branch containment, interruptibility, receipts, private-state sealing, and Bifrost-gated publication/merge/escalation, not asking a human before every local edit. Seventeen native repo-swarm front doors are live and documented there: `epiphany-repo init`, `epiphany-swarm online`, `epiphany-swarm run`, `epiphany-work accept`, `epiphany-work persona-intake`, `epiphany-work derive-plan`, `epiphany-work plan`, `epiphany-work run`, `epiphany-work adopt --from-plan`, `epiphany-work execute --from-plan`, `epiphany-work close`, `epiphany-work overview`, `epiphany-work export-proof`, `epiphany-work tick`, `epiphany-work queue-run`, `epiphany-work publish`, and `epiphany-work sync`. Fresh-repo smokes proved the chain with `privateStateExposed=false`, including deterministic Persona/Bifrost pressure-to-plan derivation (`append-worklog`, `planning-note`, and `checklist-note`) into `EPIPHANY_WORKLOG.md`, contained markdown planning notes, or contained markdown checklists, typed Imagination action-item receipts (`epiphany.repo_work_imagination_action_items_receipt.v0`) that carry model provenance, safe family, requested paths, verification asks, stop conditions, escalation reasons, and `operatorAuthoredShellDetails=false` before deterministic safe-family command lowering, plan-backed branch-local commit creation, a speech-audited repo Persona intake mouth that records public discussion refs plus candidate action refs before delegating to `accept`, a bounded `epiphany-swarm run` mouth that delegates queue selection to `epiphany-work queue-run` and item actuation to `epiphany-work tick`, a Self-owned tick pulse that advances `run-from-plan -> adopt-from-plan -> execute-from-plan -> close-from-execute` then no-ops before publication gates, local CultMesh swarm-brake refusal that writes `refused-by-swarm-brake` without creating a run/adopt/execute/close receipt, active-turn refusal through `work-tick-active-<item>.json`, explicit completion-anchored cooldown refusal through `work-tick-last-<item>.json`, stale active-turn recovery that records `physiology.recoveredActiveTurn.recovered=true`, Self-owned `epiphany-work serve` cadence that writes `work-scheduler-serve-<item>.json`, bounded serve proof `advanced:run-from-plan -> refused-by-cooldown:none` without adoption, unbounded zero-interval refusal, deterministic `epiphany-work close` proof that consumes execute receipts, verifies the Hands commit, writes Soul verdict plus Modeling summary plus Mind gateway/state-commit receipts, scheduler proof `.epiphany-smoke\tick-close-20260620-025526` that `epiphany-swarm run --max-iterations 4` reached `awaiting-publication` through `close-from-execute` with Soul passed and Mind committed, local `epiphany-work overview` proof bundle `epiphany.repo_work_proof_bundle.v0` that reports pre-plan `awaiting-plan`/`plan-receipt-missing` and post-close `awaiting-publication`/`bifrost-publication-missing` with branch, commit, changed paths, Soul verdict, compact TUI rows, expected receipt artifact paths, present/missing artifact statuses, document schemas/statuses, SHA-256 receipt hashes, publication rows for Bifrost/GitHub/credit/PR/upstream-main sync, and private seals, public `epiphany-work export-proof` packaging that writes redacted `epiphany.repo_work_public_proof_bundle.v0` artifacts without local receipt paths, raw receipt bodies, worker thought, or private Verse exposure, typed local Verse projection as `epiphany.cultmesh.repo_work_overview.v0` with latest-key/event-history readback through Gjallar plus peer-readable Persona Eve lowering, `epiphany-work queue-run` selection over tick-actionable queue rows through `awaiting-closure` with wrapper `repo-work-queue-run`, Idunn-owned non-mutating `repo-work-service-plan`/`repo-work-service-runbook` receipts for the same queue-run command, `publish --closure-receipt` consumption of the close receipt's Soul/Mind refs, post-publication tick `noop:none`, and upstream-main ancestry proof after explicit merge receipt. Remaining MVP organs are deeper model-authored safe-family breadth, Bifrost/public Verse transport for exported proof, and richer model-authored closure; the scheduler may advance only one safe receipt-backed branch-local step per pulse and must not publish, merge, mutate services, cross repo boundaries, expose private state, or impersonate Idunn.
- Use `notes/epiphany-repo-swarm-mvp-contract.md` as the authority correction and migration plan for repo-swarm autonomy. Autonomous branch-local work inside an Epiphany-owned repo Body is in scope and desired; the safety boundary is typed authority, branch containment, interruptibility, receipts, private-state sealing, and Bifrost-gated publication/merge/escalation, not asking a human before every local edit. Seventeen native repo-swarm front doors are live and documented there: `epiphany-repo init`, `epiphany-swarm online`, `epiphany-swarm run`, `epiphany-work accept`, `epiphany-work persona-intake`, `epiphany-work derive-plan`, `epiphany-work plan`, `epiphany-work run`, `epiphany-work adopt --from-plan`, `epiphany-work execute --from-plan`, `epiphany-work close`, `epiphany-work overview`, `epiphany-work export-proof`, `epiphany-work tick`, `epiphany-work queue-run`, `epiphany-work publish`, and `epiphany-work sync`. Fresh-repo smokes proved the chain with `privateStateExposed=false`, including deterministic Persona/Bifrost pressure-to-plan derivation (`append-worklog`, `planning-note`, and `checklist-note`) into `EPIPHANY_WORKLOG.md`, contained markdown planning notes, or contained markdown checklists, typed Imagination action-item receipts (`epiphany.repo_work_imagination_action_items_receipt.v0`) that carry model provenance, safe family, requested paths, verification asks, stop conditions, escalation reasons, and `operatorAuthoredShellDetails=false` before deterministic safe-family command lowering, plan-backed branch-local commit creation, a speech-audited repo Persona intake mouth that records public discussion refs plus candidate action refs before delegating to `accept`, a bounded `epiphany-swarm run` mouth that delegates queue selection to `epiphany-work queue-run` and item actuation to `epiphany-work tick`, a Self-owned tick pulse that advances `run-from-plan -> adopt-from-plan -> execute-from-plan -> close-from-execute` then no-ops before publication gates, local CultMesh swarm-brake refusal that writes `refused-by-swarm-brake` without creating a run/adopt/execute/close receipt, active-turn refusal through `work-tick-active-<item>.json`, explicit completion-anchored cooldown refusal through `work-tick-last-<item>.json`, stale active-turn recovery that records `physiology.recoveredActiveTurn.recovered=true`, Self-owned `epiphany-work serve` cadence that writes `work-scheduler-serve-<item>.json`, bounded serve proof `advanced:run-from-plan -> refused-by-cooldown:none` without adoption, unbounded zero-interval refusal, deterministic `epiphany-work close` proof that consumes execute receipts, verifies the Hands commit, writes Soul verdict plus Modeling summary plus Mind gateway/state-commit receipts, scheduler proof `.epiphany-smoke\tick-close-20260620-025526` that `epiphany-swarm run --max-iterations 4` reached `awaiting-publication` through `close-from-execute` with Soul passed and Mind committed, local `epiphany-work overview` proof bundle `epiphany.repo_work_proof_bundle.v0` that reports pre-plan `awaiting-plan`/`plan-receipt-missing` and post-close `awaiting-publication`/`bifrost-publication-missing` with branch, commit, changed paths, Soul verdict, compact TUI rows, expected receipt artifact paths, present/missing artifact statuses, document schemas/statuses, SHA-256 receipt hashes, publication rows for Bifrost/GitHub/credit/PR/upstream-main sync, and private seals, public `epiphany-work export-proof` packaging that writes redacted `epiphany.repo_work_public_proof_bundle.v0` artifacts and mirrors `epiphany.cultmesh.repo_work_public_proof.v0` rows into local Verse for Gjallar/Odin sight without local receipt paths, raw receipt bodies, worker thought, or private Verse exposure, typed local Verse projection as `epiphany.cultmesh.repo_work_overview.v0` with latest-key/event-history readback through Gjallar plus peer-readable Persona Eve lowering, `epiphany-work queue-run` selection over tick-actionable queue rows through `awaiting-closure` with wrapper `repo-work-queue-run`, Idunn-owned non-mutating `repo-work-service-plan`/`repo-work-service-runbook` receipts for the same queue-run command, `publish --closure-receipt` consumption of the close receipt's Soul/Mind refs, post-publication tick `noop:none`, and upstream-main ancestry proof after explicit merge receipt. Remaining MVP organs are deeper model-authored safe-family breadth, Bifrost/public publication transport beyond local Verse, and richer model-authored closure; the scheduler may advance only one safe receipt-backed branch-local step per pulse and must not publish, merge, mutate services, cross repo boundaries, expose private state, or impersonate Idunn.
- Gjallar/swarm-overview now projects typed repo-work overview history into the compact global sight report, Persona's public Eve surface lowers the same queue for peers, and Self has a first runnable queue surface over it. `epiphany-verse-query gjallar` reads all `epiphany.cultmesh.repo_work_overview.v0` event documents from local Verse, excludes the `latest` mirror, preserves latest scalar fields, emits multi-item `repoWorkOverviewRows`/TUI rows, and publishes bounded priority 35-39 non-mutating `repo-work-overview` action rows with `owner=Gjallar`, `hostedBody=repo-work`, `authorityGate=repo.work.overview`, `mutatesState=false`, `requiresElevatedAuthority=false`, proof-bundle refs, current gate/blocker/next-safe-move, and `privateStateExposed=false`. `epiphany-verse-query eve-surfaces`, `connect-eve`, and globally invokable Persona `eve-connect` tool readbacks expose compact `REPO-WORK-PEER` rows with item, gate, blocker, next safe move, branch, publication/sync state, and private seal for the public Persona surface only. `epiphany-work queue-run` selects current-repo rows at `ready-to-run`, `ready-to-adopt`, or `ready-to-execute`, delegates action to `tick`, refreshes overview after real advancement, and writes `epiphany.repo_work_queue_run_receipt.v0`; wrapper mode `tools/epiphany_local_run.ps1 -Mode repo-work-queue-run` exposes the same surface. Disposable proofs `.epiphany-smoke\gjallar-repo-work-queue-20260620-012027`, `.epiphany-smoke\eve-repo-work-queue-20260620-013322`, `.epiphany-smoke\queue-run-20260620-014314`, and wrapper artifact `local-20260620-014627-174-aada0241` showed two-item queues through sight, public Eve, direct queue-run, and wrapper dry-run without publication, merge, service lifecycle mutation, elevation, cross-repo mutation, or private-state exposure.
- Agent memory lifecycle now has a first typed v0 operation surface in `epiphany-core::agent_memory`: `AgentMemoryLifecycleOperation` can revise, retire, crystallize, prune, and merge bounded memory records after role/agent review, and `epiphany-agent-memory-store review-lifecycle|apply-lifecycle` exposes the path at the operator edge. This closes the first explicit lifecycle-operation slice from the swarm-readiness gate; it does not yet make sleep silently mutate identity or project truth.
- Persona public speech now has a parent-side eligibility receipt at the Discord/Aquarium mouth edge. `epiphany.persona_speech_audit.v0` records action kind, content fingerprint, opening/topic keys, recent-window counts, repeated opening/topic counts, channel saturation, and allow/block reasons. `epiphany-persona-discord post` blocks repeated public openings before token/webhook work; draft and bubble still emit audit receipts for operator inspection. The compatibility JSON artifact remains for display, but the durable witness is now `epiphany.cultmesh.persona_speech_audit.v0` in CultMesh with latest-key projection through local Verse context. Local MVP Persona bubbles now write that durable witness to `.epiphany-run/cultmesh/local-verse.ccmp`, not a separate mouth-side store. This is posting-edge policy, not a Persona prompt wish.
@ -634,4 +634,4 @@ current_status:
- `tools/epiphany_local_run.ps1 -Mode swarm-online-runbook` now emits an explicit Idunn preflight summary before the operator elevation boundary. Its JSON and one-line summary report `preflightStatus`, child artifact present/hash-verified/mismatch/missing counts, aggregate service execution failed/missing check counts, child preflight rows with expected/actual SHA-256s, and private-state exposure. Live proof `local-20260619-025627-410-9724e2f6` generated the non-mutating parent artifact with `preflightStatus=ready-for-elevated-operator`, two child runbooks present, two hashes verified, zero mismatches, zero missing artifacts, eleven failed sealed service checks, zero missing checks, explicit aftercare audits, and `privateStateExposed=false`. The remaining scar is still explicit elevated operator execution followed by complete Idunn audits, not missing parent/child artifact readiness.
- Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass.
- `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure.
next_action: Continue repo-swarm MVP work from the documented Epiphany Online cut order in `notes/epiphany-repo-swarm-mvp-contract.md`. Typed Gjallar repo-work history/queue sight, peer-readable Persona Eve lowering, Self-owned `epiphany-work queue-run`, bounded `epiphany-swarm run`, execute-to-close scheduler handoff through `close-from-execute`, deterministic `derive-plan` families `append-worklog`, `planning-note`, and `checklist-note`, typed Imagination action-item receipts over allowlisted safe families, hash-backed local proof bundles with Bifrost/GitHub/credit/PR/upstream-main publication rows, redacted `epiphany-work export-proof` public bundles, Idunn-hosted non-mutating queue-run lifecycle plan/runbook receipts, and the speech-audited `epiphany-work persona-intake` mouth plus wrapper `repo-persona-intake` are live with `privateStateExposed=false`; the next cut is Bifrost/public Verse transport for exported proof, deeper model-authored safe-family breadth, or richer model-authored closure. Preserve Idunn service lifecycle ownership and existing CultMesh/Odin/Eve tool directories; service install/start execution still requires explicit elevated operator authority.
next_action: Continue repo-swarm MVP work from the documented Epiphany Online cut order in `notes/epiphany-repo-swarm-mvp-contract.md`. Typed Gjallar repo-work history/queue sight, peer-readable Persona Eve lowering, Self-owned `epiphany-work queue-run`, bounded `epiphany-swarm run`, execute-to-close scheduler handoff through `close-from-execute`, deterministic `derive-plan` families `append-worklog`, `planning-note`, and `checklist-note`, typed Imagination action-item receipts over allowlisted safe families, hash-backed local proof bundles with Bifrost/GitHub/credit/PR/upstream-main publication rows, redacted `epiphany-work export-proof` public bundles plus local Verse `epiphany.cultmesh.repo_work_public_proof.v0` Gjallar readback, Idunn-hosted non-mutating queue-run lifecycle plan/runbook receipts, and the speech-audited `epiphany-work persona-intake` mouth plus wrapper `repo-persona-intake` are live with `privateStateExposed=false`; the next cut is Bifrost/public publication transport beyond local Verse, deeper model-authored safe-family breadth, or richer model-authored closure. Preserve Idunn service lifecycle ownership and existing CultMesh/Odin/Eve tool directories; service install/start execution still requires explicit elevated operator authority.