Wire Weksa into repo Persona intake

This commit is contained in:
Meta Vens 2026-06-21 17:48:35 +01:00
commit 77604f4668
5 changed files with 137 additions and 2 deletions

View file

@ -309,6 +309,8 @@ fn run_smoke(args: Args) -> Result<Value> {
require_eq(&publish, &["status"], "publication-receipts-recorded")?;
require_eq(&sync, &["status"], "upstream-main-synced")?;
require_eq(&export, &["status"], "public-proof-exported")?;
require_non_empty(&intake, &["weksaLoweringReceiptId"])?;
require_bool(&intake, &["privateStateExposed"], false)?;
require_bool(&overview, &["privateStateExposed"], false)?;
require_bool(&export, &["privateStateExposed"], false)?;
let close_private = close
@ -335,6 +337,7 @@ fn run_smoke(args: Args) -> Result<Value> {
"initStatus": init["status"],
"onlineStatus": online["status"],
"personaIntakeStatus": intake["status"],
"weksaLoweringReceiptId": intake["weksaLoweringReceiptId"],
"planStatus": plan["status"],
"preRunOverviewGate": pre_run_overview["gate"],
"preRunOverviewBlocker": pre_run_overview["blocker"],
@ -473,6 +476,19 @@ fn require_bool(value: &Value, path: &[&str], expected: bool) -> Result<()> {
}
}
fn require_non_empty(value: &Value, path: &[&str]) -> Result<()> {
let actual = path
.iter()
.try_fold(value, |current, key| current.get(*key))
.and_then(Value::as_str)
.unwrap_or_default();
if actual.trim().is_empty() {
Err(anyhow!("expected {} to be non-empty", path.join(".")))
} else {
Ok(())
}
}
fn take_path(
args: &mut std::iter::Peekable<impl Iterator<Item = String>>,
flag: &str,

View file

@ -10,11 +10,13 @@ use epiphany_core::EPIPHANY_CULTMESH_REPO_WORK_OVERVIEW_SCHEMA_VERSION;
use epiphany_core::EPIPHANY_CULTMESH_REPO_WORK_PUBLIC_PROOF_SCHEMA_VERSION;
use epiphany_core::EPIPHANY_CULTMESH_REPO_WORK_READINESS_REVIEW_SCHEMA_VERSION;
use epiphany_core::EPIPHANY_CULTMESH_REPO_WORK_READINESS_SCHEMA_VERSION;
use epiphany_core::EPIPHANY_CULTMESH_WEKSA_LOWERING_RECEIPT_SCHEMA_VERSION;
use epiphany_core::EpiphanyCultMeshRepoWorkMapEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkOverviewEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkPublicProofEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkReadinessEntry;
use epiphany_core::EpiphanyCultMeshRepoWorkReadinessReviewEntry;
use epiphany_core::EpiphanyCultMeshWeksaLoweringReceiptEntry;
use epiphany_core::HANDS_ACTION_INTENT_SCHEMA_VERSION;
use epiphany_core::HANDS_COMMAND_RECEIPT_TYPE;
use epiphany_core::HANDS_COMMIT_RECEIPT_TYPE;
@ -29,6 +31,10 @@ use epiphany_core::SOUL_VERDICT_RECEIPT_SCHEMA_VERSION;
use epiphany_core::SUBSTRATE_GATE_REPO_ACCESS_GRANT_RECEIPT_SCHEMA_VERSION;
use epiphany_core::SoulVerdictReceipt;
use epiphany_core::SubstrateGateRepoAccessGrantReceipt;
use epiphany_core::WeksaInterlinguaInput;
use epiphany_core::WeksaSpeakerContext;
use epiphany_core::build_weksa_interlingua_packet;
use epiphany_core::build_weksa_target_lowering_request;
use epiphany_core::hands_action_review_for_intent;
use epiphany_core::hands_command_receipt_for_review;
use epiphany_core::hands_commit_receipt_for_review;
@ -55,6 +61,7 @@ use epiphany_core::put_mind_gateway_review;
use epiphany_core::put_mind_state_commit_receipt;
use epiphany_core::put_soul_verdict_receipt;
use epiphany_core::put_substrate_gate_repo_access_grant_receipt;
use epiphany_core::record_weksa_target_lowering_receipt;
use epiphany_core::runtime_hands_action_intent;
use epiphany_core::runtime_hands_action_review;
use epiphany_core::runtime_hands_commit_receipt;
@ -64,6 +71,7 @@ use epiphany_core::write_epiphany_cultmesh_repo_work_overview;
use epiphany_core::write_epiphany_cultmesh_repo_work_public_proof;
use epiphany_core::write_epiphany_cultmesh_repo_work_readiness;
use epiphany_core::write_epiphany_cultmesh_repo_work_readiness_review;
use epiphany_core::write_epiphany_cultmesh_weksa_lowering_receipt;
use serde::Deserialize;
use serde::Serialize;
use serde_json::Value;
@ -1840,6 +1848,14 @@ fn run_persona_intake(args: PersonaIntakeArgs) -> Result<Value> {
let summary = compact_text(&args.message, 480);
let public_ref = format!("eve://epiphany/persona#repo-intake/{item_slug}/{audit_id}");
let candidate_ref = format!("candidate-action://{runtime_id}/{item_slug}/{audit_id}");
let weksa = record_repo_persona_intake_weksa(
&local_verse_store,
&runtime_id,
&item_slug,
&audit_id,
&args.message,
&public_ref,
)?;
let accept = run_accept(AcceptArgs {
workspace: workspace.clone(),
epiphany_root: epiphany_root.clone(),
@ -1871,7 +1887,8 @@ fn run_persona_intake(args: PersonaIntakeArgs) -> Result<Value> {
"speechAudit": speech_audit,
"contentFingerprint": content_fingerprint,
"publicDiscussionRef": public_ref,
"candidateActionRef": candidate_ref
"candidateActionRef": candidate_ref,
"weksa": weksa
},
"accept": accept,
"authority": {
@ -1898,6 +1915,7 @@ fn run_persona_intake(args: PersonaIntakeArgs) -> Result<Value> {
"receiptPath": receipt_path,
"item": receipt["item"],
"speechAuditId": audit_id,
"weksaLoweringReceiptId": receipt["persona"]["weksa"]["receiptId"],
"bubblePath": receipt["persona"]["bubblePath"],
"acceptReceiptPath": accept["receiptPath"],
"feedback": accept["feedback"],
@ -1907,6 +1925,101 @@ fn run_persona_intake(args: PersonaIntakeArgs) -> Result<Value> {
}))
}
fn record_repo_persona_intake_weksa(
local_verse_store: &Path,
runtime_id: &str,
item_slug: &str,
audit_id: &str,
message: &str,
public_ref: &str,
) -> Result<Value> {
let audit_slug = sanitize(audit_id);
let packet_id = format!("weksa-packet-repo-intake-{item_slug}-{audit_slug}");
let request_id = format!("weksa-lower-repo-intake-{item_slug}-{audit_slug}");
let receipt_id = format!("weksa-lowering-repo-intake-{item_slug}-{audit_slug}");
let delivery_surface = "eve://epiphany/persona";
let target_language = "en";
let target_register = "repo-public-intake";
let packet = build_weksa_interlingua_packet(WeksaInterlinguaInput {
packet_id: packet_id.clone(),
source_interpreter_ref: format!("persona-intake:{runtime_id}:{item_slug}:{audit_slug}"),
source_speech_audit_ref: audit_id.to_string(),
speaker: WeksaSpeakerContext {
persona_id: "epiphany.Persona".to_string(),
display_name: "Epiphany".to_string(),
source_surface: delivery_surface.to_string(),
source_language: "en".to_string(),
utterance_state_ref: "state/agents.msgpack#Persona:utterance-state".to_string(),
},
meaning: message.to_string(),
speech_act: "repo-intake-say".to_string(),
delivery_register: target_register.to_string(),
target_audience: "repo-public-room".to_string(),
safety_notes: vec![
"Do not claim Hands, Bifrost, publication, merge, deployment, or service lifecycle authority.".to_string(),
"Do not expose private worker thought, raw result payloads, or private Verse state.".to_string(),
],
})?;
let request = build_weksa_target_lowering_request(
request_id.clone(),
packet,
target_language,
target_register,
delivery_surface,
)?;
let receipt = record_weksa_target_lowering_receipt(
&request,
receipt_id.clone(),
message.to_string(),
"repo-persona-intake-local-text-lowering",
)?;
let lowered_text_preview = compact_text(&receipt.lowered_text, 480);
let cultmesh_receipt = EpiphanyCultMeshWeksaLoweringReceiptEntry {
schema_version: EPIPHANY_CULTMESH_WEKSA_LOWERING_RECEIPT_SCHEMA_VERSION.to_string(),
receipt_id: receipt.receipt_id.clone(),
runtime_id: runtime_id.to_string(),
verse_id: EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID.to_string(),
packet_id: receipt.packet_id.clone(),
request_id: receipt.request_id.clone(),
persona_agent_id: request.packet.speaker.persona_id.clone(),
target_language: receipt.target_language.clone(),
target_register: receipt.target_register.clone(),
delivery_surface: receipt.delivery_surface.clone(),
lowering_method: receipt.lowering_method.clone(),
transport_authority: receipt.transport_authority.clone(),
publication_authorized: false,
lowered_text_ref: public_ref.to_string(),
lowered_text_preview,
created_at_utc: Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
private_state_exposed: false,
notes: vec![
"Repo Persona intake routed public SAY through Weksa interlingua/lowering before any mouth transport publication.".to_string(),
],
};
write_epiphany_cultmesh_weksa_lowering_receipt(local_verse_store, cultmesh_receipt)?;
Ok(json!({
"schemaVersion": "epiphany.repo_persona_intake_weksa.v0",
"packetSchemaVersion": request.packet.schema_version,
"requestSchemaVersion": request.schema_version,
"receiptSchemaVersion": receipt.schema_version,
"cultmeshSchemaVersion": EPIPHANY_CULTMESH_WEKSA_LOWERING_RECEIPT_SCHEMA_VERSION,
"packetId": packet_id,
"requestId": request_id,
"receiptId": receipt_id,
"sourceSpeechAuditRef": audit_id,
"targetLanguage": receipt.target_language,
"targetRegister": receipt.target_register,
"deliverySurface": receipt.delivery_surface,
"loweringMethod": receipt.lowering_method,
"transportAuthority": receipt.transport_authority,
"loweredTextRef": public_ref,
"modelRequired": request.model_required,
"publicationAuthorized": false,
"privateStateExposed": false,
}))
}
fn run_work(args: RunArgs) -> Result<Value> {
let workspace = args
.workspace

View file

@ -1526,6 +1526,12 @@ Epiphany has the first native slice of that membrane in `epiphany-core`:
contracts, heartbeat state carries typed pending mentions, and pending Persona
mentions select a `persona_turn` without letting Persona side effects execute
themselves.
Repo Persona intake now carries the Weksa side of the membrane too:
`epiphany-work persona-intake` turns public SAY into a Weksa interlingua packet,
target-language lowering request, lowering receipt, and local Verse
`epiphany.cultmesh.weksa_lowering_receipt.v0` mirror before any mouth transport
publication. The receipt-directory row is Weksa-owned sight only; Bifrost or the
configured mouth edge still owns publication, and Mind still owns durable state.
`notes/organ-dependency-contracts.md` is the standing dependency map: every
sub-agent depends on all the other standing sub-agents. Dependency does not collapse
ownership; it makes each turn whole-organism-aware while Substrate Gate still gates repo

Binary file not shown.

View file

@ -649,5 +649,5 @@ 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.
last_completed_repo_swarm_cut: The artifact-acceptance and metrics request family smokes now prove the whole Bifrost accounting transition, not only the request side. Each smoke first asserts the Mind-admitted safe-family request row is `open`, then writes the final Bifrost/Maintainer receipt, rereads `bifrost-ledger`, and asserts the same lane is `closed` from explicit receipt evidence with `privateStateExposed=false`. Latest proofs `.epiphany-smoke\repo-artifact-acceptance-request-family-20260621-130520` and `.epiphany-smoke\repo-metrics-request-family-20260621-130635`; wrapper proof `local-20260621-140740-750-2815f6f7` printed the closed metrics row from a repo-local Verse target.
last_completed_repo_swarm_cut: Repo Persona intake now routes public Persona SAY through Weksa interlingua/lowering cargo on the normal product path, not only through the isolated Weksa smoke. `epiphany-work persona-intake` builds a Weksa interlingua packet, target-language lowering request, lowering receipt, and local Verse `epiphany.cultmesh.weksa_lowering_receipt.v0` mirror while denying publication, durable-state, Hands, merge, deployment, service lifecycle, and private-state authority. Direct proof on disposable fresh-repo fixture `.epiphany-smoke\fresh-repo-mvp-20260621-164107\repo-body` returned `weksaLoweringReceiptId=weksa-lowering-repo-intake-fresh-repo-mvp-persona-speech-audit-7863b4c6`; receipt-directory readback reported `OK | Weksa | weksa-lowering | lowered:en | route=eve://epiphany/persona | privateStateExposed=false`. The fresh-repo MVP smoke now asserts Persona intake returns a non-empty Weksa lowering receipt id.
next_action: Continue repo-swarm MVP work from `notes/epiphany-repo-swarm-mvp-contract.md`. The aggregate MVP gate is now sealed: `tools/epiphany_local_run.ps1 -Mode repo-swarm-mvp-gate` reports `demoReady=true`, `mvpReady=false`, thirteen green proof gates, one Idunn elevated-service warning gate, zero blockers, and `privateStateExposed=false`. Useful next cuts are live-fire testing on a disposable or low-stakes repo Body, explicit elevated/operator Idunn execution proof only when the human grants that authority, or another repo-owned safe action family only if it materially improves the MVP story. Persona-to-Imagination consensus readback, Mind-owned interpreter brief cargo, safe-family planning depth and closure, Gjallar closure/readiness/readiness-review rows, receipt-directory readiness-review indexing, Bifrost ledger accounting rows including readiness-review closure plus artifact/metrics final receipt closure, readiness wrapper mouth, repo deployment handoff/readback wrappers, readiness deployment-aftercare closure, readiness Idunn/tool-directory receipt validation, readiness Bifrost/GitHub publication-chain validation, readiness upstream-main sync validation, readiness review/adoption receipt validation, aggregate fresh-repo/readiness/Bifrost/deployment-handoff/daemon-survival MVP gate reporting, and bounded Idunn daemon survival rehearsal are sealed; preserve Idunn service lifecycle ownership, Bifrost publication/upstream-main ownership, Mind durable-state admission, and existing CultMesh/Odin/Eve tool directories. Windows service install/start/deployment execution still requires explicit elevated operator authority.