From 77604f4668f346db0eb2d8fa92555b9e5d0d2c23 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 21 Jun 2026 17:48:35 +0100 Subject: [PATCH] Wire Weksa into repo Persona intake --- .../src/bin/epiphany-repo-swarm-mvp-smoke.rs | 16 +++ epiphany-core/src/bin/epiphany-work.rs | 115 +++++++++++++++++- notes/fresh-workspace-handoff.md | 6 + state/ledgers.msgpack | Bin 380722 -> 381210 bytes state/map.yaml | 2 +- 5 files changed, 137 insertions(+), 2 deletions(-) diff --git a/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs b/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs index 2577ec1c..fc4ede05 100644 --- a/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs +++ b/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs @@ -309,6 +309,8 @@ fn run_smoke(args: Args) -> Result { 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 { "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>, flag: &str, diff --git a/epiphany-core/src/bin/epiphany-work.rs b/epiphany-core/src/bin/epiphany-work.rs index 57752b13..89112076 100644 --- a/epiphany-core/src/bin/epiphany-work.rs +++ b/epiphany-core/src/bin/epiphany-work.rs @@ -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 { 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 { "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 { "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 { })) } +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 { + 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 { let workspace = args .workspace diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 4b797a2e..a5548b5f 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -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 diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 426c2600da26221eef73aa5ce89b6fc1723f1404..649f48bb5061bd0e1c566b2204c37137943847fe 100644 GIT binary patch delta 353 zcmdlqPkh!Q@eLA;+$QE$rsh${7+BAL->l47$jI2+Je8?^Dib3RgJ@mgg5`D-?iioX&HYg^MFKH?yQzAyHv^!&z1_ zc7@Cog~Ys+>Hnv)N>6`xmQ_j+=%{>!ocv^X8-K6}KN(B(B2xzXqH`KvkN2aD&rA`mDW>#Rg@eLA;+{Ol0hL%ys7+BBoZ&qe3WMu4Vp32ldm5C9EK{PWEvuvNr#5(s3 E0K;w&#sB~S diff --git a/state/map.yaml b/state/map.yaml index 3c2f4c22..5685b646 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -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.