diff --git a/epiphany-core/src/bin/epiphany-persona-discord.rs b/epiphany-core/src/bin/epiphany-persona-discord.rs index 6eb75a1a..66a5de35 100644 --- a/epiphany-core/src/bin/epiphany-persona-discord.rs +++ b/epiphany-core/src/bin/epiphany-persona-discord.rs @@ -47,7 +47,6 @@ fn main() -> Result<()> { let mut content: Option = None; let mut channel_id: Option = None; let mut source = "epiphany/Persona".to_string(); - let mut status = "ready".to_string(); let mut mood = "attentive".to_string(); let mut limit = 8_usize; let mut persona_name: Option = None; @@ -63,7 +62,6 @@ fn main() -> Result<()> { "--content" => content = Some(next_value(&mut args, "--content")?), "--channel-id" => channel_id = Some(next_value(&mut args, "--channel-id")?), "--source" => source = next_value(&mut args, "--source")?, - "--status" => status = next_value(&mut args, "--status")?, "--mood" => mood = next_value(&mut args, "--mood")?, "--limit" => limit = next_value(&mut args, "--limit")?.parse()?, "--persona-name" => persona_name = Some(next_value(&mut args, "--persona-name")?), @@ -99,7 +97,6 @@ fn main() -> Result<()> { &cultmesh_store, &runtime_id, &source, - &status, &mood, )? } @@ -168,7 +165,6 @@ fn run_bubble( cultmesh_store: &Path, runtime_id: &str, source: &str, - status: &str, mood: &str, ) -> Result { ensure_content(content, "Persona bubble")?; @@ -181,7 +177,7 @@ fn run_bubble( None, false, )?; - let payload = bubble_payload(content, source, status, mood); + let payload = bubble_payload(content, source, mood); let path = artifact_dir.join(format!( "Persona-bubble-{}-{}.json", now_stamp(), @@ -753,7 +749,6 @@ console.log(JSON.stringify({ &cultmesh_store, runtime_id, "smoke/Persona", - "ready", "attentive", )?; let blocked = run_post( @@ -937,11 +932,11 @@ fn write_draft( Ok(path) } -fn bubble_payload(content: &str, source: &str, status: &str, mood: &str) -> Value { +fn bubble_payload(content: &str, source: &str, mood: &str) -> Value { serde_json::json!({ "schema_version": BUBBLE_SCHEMA_VERSION, "created_at": now_iso(), - "status": status, + "status": "projected", "source": source, "target": "aquarium", "role_id": "Persona", diff --git a/notes/conceptual-substitution-audit-2026-07-12.md b/notes/conceptual-substitution-audit-2026-07-12.md index 2e1163b7..319f079d 100644 --- a/notes/conceptual-substitution-audit-2026-07-12.md +++ b/notes/conceptual-substitution-audit-2026-07-12.md @@ -1518,3 +1518,13 @@ for repetition pressure. It now records `crossing_recorded` and counts effects; it no longer implies that an outside provider published them. The v0 serialized `sameTargetPostCount` field remains only as a compatibility name and does not own the internal model. + +## Caller presentation text is not bubble readiness + +The Discord Persona bubble CLI accepted arbitrary `--status` text, while the +MVP wrapper supplied `ready`. That let a caller author an Aquarium-visible +lifecycle verdict with no owner or evidence. The option is deleted. Successful +bubble projection derives `status=projected`; the intent schema rejects unknown +fields and the output schema admits only that derived value. Mood and source +remain presentation metadata. A negative CLI check proves `--status ready` is +rejected before artifact creation. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index ad967267..289cda55 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -587,3 +587,9 @@ posts. Recent speech tracks `crossing_recorded` and transport receipt. The old v0 `sameTargetPostCount` spelling is serialization- only compatibility. Native Other-mouth smoke, 259 library tests, and all-bin compilation pass. + +Persona Aquarium bubbles no longer accept caller-authored readiness. The CLI +has no `--status`; successful writes derive `projected`; the strict intent +schema has no status field; and the output schema permits only `projected`. +Native smoke returns that value and an explicit `--status ready` invocation is +rejected. The 259 library tests and all-bin check pass. diff --git a/schemas/cultnet/epiphany.persona-bubble.schema.json b/schemas/cultnet/epiphany.persona-bubble.schema.json index 70c4f724..95282eb5 100644 --- a/schemas/cultnet/epiphany.persona-bubble.schema.json +++ b/schemas/cultnet/epiphany.persona-bubble.schema.json @@ -13,7 +13,10 @@ "type": "string" }, "status": { - "type": "string" + "type": "string", + "enum": [ + "projected" + ] }, "source": { "type": "string" diff --git a/schemas/cultnet/epiphany.persona_bubble_intent.v0.schema.json b/schemas/cultnet/epiphany.persona_bubble_intent.v0.schema.json index 35d5526a..f230ccfd 100644 --- a/schemas/cultnet/epiphany.persona_bubble_intent.v0.schema.json +++ b/schemas/cultnet/epiphany.persona_bubble_intent.v0.schema.json @@ -4,7 +4,7 @@ "title": "epiphany persona_bubble_intent v0", "description": "Persona bubble intent for Aquarium-visible chat puffs.", "type": "object", - "additionalProperties": true, + "additionalProperties": false, "properties": { "threadId": { "type": "string" @@ -15,9 +15,6 @@ "source": { "type": "string" }, - "status": { - "type": "string" - }, "mood": { "type": "string" } diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index be16d642..c2d7d6fe 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 635b1b07..f1c55228 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -660,4 +660,4 @@ current_status: - 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: Huginn live-fire has crossed the first real repo Body from Persona pressure to branch-local Hands commit and Soul/Mind closure, and now has repeatable closure and redacted-public-proof mouths. On `E:\Projects\Huginn` branch `epiphany/huginn/first-awakening`, `tools/epiphany_local_run.ps1 -Mode repo-persona-intake` accepted item `huginn-inspection-readback-livefire`, Weksa/Persona intake remained sealed, and `epiphany-work derive-plan` lowered it to model-authored safe family `repo.status_section` for `README.md` only. `tools/epiphany_local_run.ps1 -Mode repo-swarm-run` advanced four bounded pulses: run-from-plan, adopt-from-plan, execute-from-plan, and close-from-execute. Huginn commit `e9b07c38fceabbdc89ea35c2156326c80c0393a2` updated only `README.md`; closure receipt `.epiphany\work\work-close-huginn-inspection-readback-livefire.json` records status `closed`, Soul verdict `passed`, Mind state commit `repo-work-close-huginn-inspection-readback-livefire-mind-commit`, safe family `repo.status_section`, path scope `README.md`, Bifrost publication gate, and `privateStateExposed=false`. Verification also ran Huginn's TypeScript compiler through concrete Node path: `C:\Program Files\nodejs\node.exe E:\Projects\Huginn\node_modules\typescript\bin\tsc -p tsconfig.json` passed. Native verifier `epiphany-repo-livefire-closure-smoke --workspace E:\Projects\Huginn --item huginn-inspection-readback-livefire --expected-path README.md --expected-family repo.status_section --expected-gate awaiting-publication --expected-blocker bifrost-publication-missing` checks closure receipt, Mind map entry, overview gate/blocker, authority seals, and `git show` changed paths, returning `status=ok`, `soulVerdict=passed`, `publicationGate=Bifrost`, and `privateStateExposed=false`. Wrapper `tools/epiphany_local_run.ps1 -Mode repo-livefire-closure -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exposes the same read-only proof through the local operator mouth; artifact `local-20260621-190156-803-2f85ba15` printed commit, path, gate, blocker, Soul verdict, Mind commit receipt, and `privateStateExposed=False` without push, merge, publication, or target mutation. New wrapper `tools/epiphany_local_run.ps1 -Mode repo-work-public-proof -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exports the redacted proof bundle and repo-local Verse index without publishing; artifact `local-20260621-190645-345-4555b1dc` wrote `.epiphany\public\proof-bundles\repo-work-public-proof-huginn-inspection-readback-livefire.json`, proof id `repo-work-public-proof-huginn-inspection-readback-livefire`, SHA-256 `857545b199f3e37eb06c2e757e5cfc201958e46667bb1f8403fd333a22620f63`, nine artifact rows, zero publication rows, and `privateStateExposed=False`. swarm overview readback `local-20260621-190701-140-b9519ec6` sees the `REPO-WORK-PUBLIC-PROOF` row and action row from Huginn's repo-local Verse with the same SHA-256 while Bifrost publication remains missing. Launcher compact modes are now named compact operator-context modes instead of read-only modes, and `bifrost-public-proof` summaries print item, target public Verse, room, proof SHA-256, review receipts, and credit receipts so publication receipts are auditable without claiming upstream sync. - next_action: Continue the observation-to-consequence audit. Provider readiness no longer becomes live transport, and the Persona Other mouth models Bifrost request crossings rather than posts; only external transport receipts prove publication. Next inspect caller-controlled Persona draft/bubble statuses and Discord/Reddit receipt validation for caller text or receipt presence standing in for eligibility or successful publication. Keep closure's zero-substring invariant. + next_action: Continue the observation-to-consequence audit. Persona bubbles derive `projected`; callers cannot inject readiness through CLI or typed intent. Next inspect character-loop caller status, Persona draft helper parameters, and Discord/Reddit bridge receipt validation for caller text or receipt presence standing in for eligibility, completion, or successful publication. Keep closure's zero-substring invariant. diff --git a/tools/epiphany_local_run.ps1 b/tools/epiphany_local_run.ps1 index b9f9af21..ca727520 100644 --- a/tools/epiphany_local_run.ps1 +++ b/tools/epiphany_local_run.ps1 @@ -2411,7 +2411,6 @@ if ($Mode -eq "mvp") { "--runtime-id", $LocalVerseRuntimeId, "--content", $PersonaInput, "--source", "epiphany/local-mvp", - "--status", "ready", "--mood", "attentive" ) ` -WorkingDirectory $Root `